summaryrefslogtreecommitdiff
path: root/sql/sql_class.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_class.cc')
-rw-r--r--sql/sql_class.cc139
1 files changed, 134 insertions, 5 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 0165aa9f6e5..f77ef114d2d 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -5186,6 +5186,134 @@ show_query_type(THD::enum_binlog_query_type qtype)
}
#endif
+/*
+ Constants required for the limit unsafe warnings suppression
+*/
+//seconds after which the limit unsafe warnings suppression will be activated
+#define LIMIT_UNSAFE_WARNING_ACTIVATION_TIMEOUT 50
+//number of limit unsafe warnings after which the suppression will be activated
+#define LIMIT_UNSAFE_WARNING_ACTIVATION_THRESHOLD_COUNT 50
+
+static ulonglong limit_unsafe_suppression_start_time= 0;
+static bool unsafe_warning_suppression_is_activated= false;
+static int limit_unsafe_warning_count= 0;
+
+/**
+ Auxiliary function to reset the limit unsafety warning suppression.
+*/
+static void reset_binlog_unsafe_suppression()
+{
+ DBUG_ENTER("reset_binlog_unsafe_suppression");
+ unsafe_warning_suppression_is_activated= false;
+ limit_unsafe_warning_count= 0;
+ limit_unsafe_suppression_start_time= my_interval_timer()/10000000;
+ DBUG_VOID_RETURN;
+}
+
+/**
+ Auxiliary function to print warning in the error log.
+*/
+static void print_unsafe_warning_to_log(int unsafe_type, char* buf,
+ char* query)
+{
+ DBUG_ENTER("print_unsafe_warning_in_log");
+ sprintf(buf, ER(ER_BINLOG_UNSAFE_STATEMENT),
+ ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]));
+ sql_print_warning(ER(ER_MESSAGE_AND_STATEMENT), buf, query);
+ DBUG_VOID_RETURN;
+}
+
+/**
+ Auxiliary function to check if the warning for limit unsafety should be
+ thrown or suppressed. Details of the implementation can be found in the
+ comments inline.
+ SYNOPSIS:
+ @params
+ buf - buffer to hold the warning message text
+ unsafe_type - The type of unsafety.
+ query - The actual query statement.
+
+ TODO: Remove this function and implement a general service for all warnings
+ that would prevent flooding the error log.
+*/
+static void do_unsafe_limit_checkout(char* buf, int unsafe_type, char* query)
+{
+ ulonglong now= 0;
+ DBUG_ENTER("do_unsafe_limit_checkout");
+ DBUG_ASSERT(unsafe_type == LEX::BINLOG_STMT_UNSAFE_LIMIT);
+ limit_unsafe_warning_count++;
+ /*
+ INITIALIZING:
+ If this is the first time this function is called with log warning
+ enabled, the monitoring the unsafe warnings should start.
+ */
+ if (limit_unsafe_suppression_start_time == 0)
+ {
+ limit_unsafe_suppression_start_time= my_interval_timer()/10000000;
+ print_unsafe_warning_to_log(unsafe_type, buf, query);
+ }
+ else
+ {
+ if (!unsafe_warning_suppression_is_activated)
+ print_unsafe_warning_to_log(unsafe_type, buf, query);
+
+ if (limit_unsafe_warning_count >=
+ LIMIT_UNSAFE_WARNING_ACTIVATION_THRESHOLD_COUNT)
+ {
+ now= my_interval_timer()/10000000;
+ if (!unsafe_warning_suppression_is_activated)
+ {
+ /*
+ ACTIVATION:
+ We got LIMIT_UNSAFE_WARNING_ACTIVATION_THRESHOLD_COUNT warnings in
+ less than LIMIT_UNSAFE_WARNING_ACTIVATION_TIMEOUT we activate the
+ suppression.
+ */
+ if ((now-limit_unsafe_suppression_start_time) <=
+ LIMIT_UNSAFE_WARNING_ACTIVATION_TIMEOUT)
+ {
+ unsafe_warning_suppression_is_activated= true;
+ DBUG_PRINT("info",("A warning flood has been detected and the limit \
+unsafety warning suppression has been activated."));
+ }
+ else
+ {
+ /*
+ there is no flooding till now, therefore we restart the monitoring
+ */
+ limit_unsafe_suppression_start_time= my_interval_timer()/10000000;
+ limit_unsafe_warning_count= 0;
+ }
+ }
+ else
+ {
+ /*
+ Print the suppression note and the unsafe warning.
+ */
+ sql_print_information("The following warning was suppressed %d times \
+during the last %d seconds in the error log",
+ limit_unsafe_warning_count,
+ (int)
+ (now-limit_unsafe_suppression_start_time));
+ print_unsafe_warning_to_log(unsafe_type, buf, query);
+ /*
+ DEACTIVATION: We got LIMIT_UNSAFE_WARNING_ACTIVATION_THRESHOLD_COUNT
+ warnings in more than LIMIT_UNSAFE_WARNING_ACTIVATION_TIMEOUT, the
+ suppression should be deactivated.
+ */
+ if ((now - limit_unsafe_suppression_start_time) >
+ LIMIT_UNSAFE_WARNING_ACTIVATION_TIMEOUT)
+ {
+ reset_binlog_unsafe_suppression();
+ DBUG_PRINT("info",("The limit unsafety warning supression has been \
+deactivated"));
+ }
+ }
+ limit_unsafe_warning_count= 0;
+ }
+ }
+ DBUG_VOID_RETURN;
+}
/**
Auxiliary method used by @c binlog_query() to raise warnings.
@@ -5195,6 +5323,7 @@ show_query_type(THD::enum_binlog_query_type qtype)
*/
void THD::issue_unsafe_warnings()
{
+ char buf[MYSQL_ERRMSG_SIZE * 2];
DBUG_ENTER("issue_unsafe_warnings");
/*
Ensure that binlog_unsafe_warning_flags is big enough to hold all
@@ -5220,17 +5349,16 @@ void THD::issue_unsafe_warnings()
ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]));
if (global_system_variables.log_warnings)
{
- char buf[MYSQL_ERRMSG_SIZE * 2];
- sprintf(buf, ER(ER_BINLOG_UNSAFE_STATEMENT),
- ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]));
- sql_print_warning(ER(ER_MESSAGE_AND_STATEMENT), buf, query());
+ if (unsafe_type == LEX::BINLOG_STMT_UNSAFE_LIMIT)
+ do_unsafe_limit_checkout( buf, unsafe_type, query());
+ else //cases other than LIMIT unsafety
+ print_unsafe_warning_to_log(unsafe_type, buf, query());
}
}
}
DBUG_VOID_RETURN;
}
-
/**
Log the current query.
@@ -5406,3 +5534,4 @@ bool Discrete_intervals_list::append(Discrete_interval *new_interval)
}
#endif /* !defined(MYSQL_CLIENT) */
+