mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 12:32:27 +01:00
Auto merge
This commit is contained in:
commit
8db1f728e6
11 changed files with 120 additions and 112 deletions
|
@ -67,7 +67,7 @@ DROP TABLE t1;
|
|||
SET GLOBAL log_warnings = @old_log_warnings;
|
||||
# Count the number of times the "Unsafe" message was printed
|
||||
# to the error log.
|
||||
Occurrences: 1
|
||||
Occurrences: 0
|
||||
create table t1 (n1 int, n2 int, n3 int,
|
||||
key (n1, n2, n3),
|
||||
key (n2, n3, n1),
|
||||
|
|
|
@ -2706,8 +2706,6 @@ Warnings:
|
|||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. CREATE... REPLACE SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are replaced. This order cannot be predicted and may differ on master and the slave.
|
||||
INSERT INTO insert_2_keys VALUES (1, 2)
|
||||
ON DUPLICATE KEY UPDATE a=VALUES(a)+10, b=VALUES(b)+10;
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe
|
||||
DROP TABLE filler_table;
|
||||
DROP TABLE insert_table;
|
||||
DROP TABLE update_table;
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
|
||||
|
||||
|
||||
This directory includes a set of three test suites aimed as testing functionality
|
||||
in an engine independent way, that is - the tests should work identically against
|
||||
different engines.
|
||||
|
||||
This directory includes a set of three test suites aimed as testing
|
||||
functionality in an engine independent way, that is - the tests should
|
||||
work identically against different engines.
|
||||
|
||||
The following suites are included:
|
||||
|
||||
1) 'funcs' suite
|
||||
-------------
|
||||
A collection of functional tests covering basic engine and server functionality that can be run
|
||||
against iany engine.
|
||||
A collection of functional tests covering basic engine and server
|
||||
functionality that can be run against any engine.
|
||||
|
||||
To run the test suite:
|
||||
cd INSTALL_DIR/mysql-test
|
||||
|
@ -19,7 +15,7 @@ The following suites are included:
|
|||
|
||||
2) 'iuds' suite
|
||||
------------
|
||||
Similar to the above focused on insert/update/delete operations of different different data types.
|
||||
Similar to the above focused on insert/update/delete operations of different data types.
|
||||
|
||||
To run the test suite:
|
||||
cd INSTALL_DIR/mysql-test
|
||||
|
@ -44,13 +40,13 @@ The following suites are included:
|
|||
3) Copy the 'init_innodb.txt' file to 'init_<engine>.txt file and change its content to be "init_<engine>".
|
||||
4) In the 't' directory copy the "init_innodb.test" file to "init_<engine>.test" and change the value of
|
||||
the '$engine' variable to <engine>.
|
||||
5) In the 'r' directory copy "the init_innodb.result" file to "init_<engine>.result" and change refrences
|
||||
5) In the 'r' directory copy "the init_innodb.result" file to "init_<engine>.result" and change references
|
||||
to 'InnoDB' to <engine>.
|
||||
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
1) The folowing tests in the 'iuds' suite:
|
||||
1) The following tests in the 'iuds' suite:
|
||||
- delete_decimal
|
||||
- insert_decimal
|
||||
- update_decimal
|
||||
|
@ -63,9 +59,9 @@ Known Issues
|
|||
- ix_unique_string_length (bug 52056, masked by an 'Out of memory error' on some 32-bit platforms)
|
||||
Add the '--force' option to prevent the test run from aborting.
|
||||
|
||||
3) Some of the rpl_xxx tests in the 'funcs' suite require a secific binlog_forat setting and will be
|
||||
skipped otherwise.
|
||||
|
||||
4) Some of the rpl_xxx tests in the 'funcs' suite will report a 'Statement unsafe for replication' warning
|
||||
when run againsr a server configured to use statement based replication.
|
||||
3) Some of the rpl_xxx tests in the 'funcs' suite require a specific
|
||||
binlog_format setting and will be skipped otherwise.
|
||||
|
||||
4) Some of the rpl_xxx tests in the 'funcs' suite will report a
|
||||
'Statement unsafe for replication' warning when run against a
|
||||
server configured to use statement based replication.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
drop procedure if exists check_instrument;
|
||||
truncate table performance_schema.events_statements_summary_by_digest;
|
||||
flush status;
|
||||
create procedure check_instrument(in instr_name varchar(128))
|
||||
begin
|
||||
declare count_expected integer;
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
drop procedure if exists check_instrument;
|
||||
--enable_warnings
|
||||
|
||||
# reset counters
|
||||
truncate table performance_schema.events_statements_summary_by_digest;
|
||||
flush status;
|
||||
|
||||
delimiter $;
|
||||
create procedure check_instrument(in instr_name varchar(128))
|
||||
begin
|
||||
|
|
|
@ -5,8 +5,6 @@ call mtr.add_suppression("Unsafe statement written to the binary log using state
|
|||
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b INT,
|
||||
UNIQUE(b));
|
||||
INSERT INTO t1(b) VALUES(1),(1),(2) ON DUPLICATE KEY UPDATE t1.b=10;
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 10
|
||||
|
|
|
@ -9640,7 +9640,7 @@ set_binlog_snapshot_file(const char *src)
|
|||
Copy out current values of status variables, for SHOW STATUS or
|
||||
information_schema.global_status.
|
||||
|
||||
This is called only under LOCK_status, so we can fill in a static array.
|
||||
This is called only under LOCK_show_status, so we can fill in a static array.
|
||||
*/
|
||||
void
|
||||
TC_LOG_BINLOG::set_status_variables(THD *thd)
|
||||
|
|
|
@ -5304,6 +5304,7 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count,
|
|||
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST);
|
||||
}
|
||||
|
||||
#ifdef NOT_USED_IN_MARIADB
|
||||
/*
|
||||
INSERT...ON DUPLICATE KEY UPDATE on a table with more than one unique keys
|
||||
can be unsafe.
|
||||
|
@ -5329,6 +5330,7 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count,
|
|||
thd->lex->duplicates == DUP_UPDATE)
|
||||
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We have to emulate LOCK TABLES if we are statement needs prelocking. */
|
||||
if (thd->lex->requires_prelocking())
|
||||
|
|
176
sql/sql_class.cc
176
sql/sql_class.cc
|
@ -5974,23 +5974,35 @@ show_query_type(THD::enum_binlog_query_type qtype)
|
|||
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
|
||||
#define LIMIT_UNSAFE_WARNING_ACTIVATION_TIMEOUT 5*60
|
||||
//number of limit unsafe warnings after which the suppression will be activated
|
||||
#define LIMIT_UNSAFE_WARNING_ACTIVATION_THRESHOLD_COUNT 50
|
||||
#define LIMIT_UNSAFE_WARNING_ACTIVATION_THRESHOLD_COUNT 10
|
||||
|
||||
static ulonglong limit_unsafe_suppression_start_time= 0;
|
||||
static bool unsafe_warning_suppression_is_activated= false;
|
||||
static int limit_unsafe_warning_count= 0;
|
||||
static ulonglong unsafe_suppression_start_time= 0;
|
||||
static bool unsafe_warning_suppression_active[LEX::BINLOG_STMT_UNSAFE_COUNT];
|
||||
static ulong unsafe_warnings_count[LEX::BINLOG_STMT_UNSAFE_COUNT];
|
||||
static ulong total_unsafe_warnings_count;
|
||||
|
||||
/**
|
||||
Auxiliary function to reset the limit unsafety warning suppression.
|
||||
This is done without mutex protection, but this should be good
|
||||
enough as it doesn't matter if we loose a couple of suppressed
|
||||
messages or if this is called multiple times.
|
||||
*/
|
||||
static void reset_binlog_unsafe_suppression()
|
||||
|
||||
static void reset_binlog_unsafe_suppression(ulonglong now)
|
||||
{
|
||||
uint i;
|
||||
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;
|
||||
|
||||
unsafe_suppression_start_time= now;
|
||||
total_unsafe_warnings_count= 0;
|
||||
|
||||
for (i= 0 ; i < LEX::BINLOG_STMT_UNSAFE_COUNT ; i++)
|
||||
{
|
||||
unsafe_warnings_count[i]= 0;
|
||||
unsafe_warning_suppression_active[i]= 0;
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -6008,95 +6020,94 @@ static void print_unsafe_warning_to_log(int unsafe_type, char* buf,
|
|||
}
|
||||
|
||||
/**
|
||||
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.
|
||||
Auxiliary function to check if the warning for unsafe repliction statements
|
||||
should be thrown or suppressed.
|
||||
|
||||
Logic is:
|
||||
- If we get more than LIMIT_UNSAFE_WARNING_ACTIVATION_THRESHOLD_COUNT errors
|
||||
of one type, that type of errors will be suppressed for
|
||||
LIMIT_UNSAFE_WARNING_ACTIVATION_TIMEOUT.
|
||||
- When the time limit has been reached, all suppression is reset.
|
||||
|
||||
This means that if one gets many different types of errors, some of them
|
||||
may be reset less than LIMIT_UNSAFE_WARNING_ACTIVATION_TIMEOUT. However at
|
||||
least one error is disable for this time.
|
||||
|
||||
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.
|
||||
RETURN:
|
||||
0 0k to log
|
||||
1 Message suppressed
|
||||
*/
|
||||
static void do_unsafe_limit_checkout(char* buf, int unsafe_type, char* query)
|
||||
|
||||
static bool protect_against_unsafe_warning_flood(int unsafe_type)
|
||||
{
|
||||
ulonglong now= 0;
|
||||
DBUG_ENTER("do_unsafe_limit_checkout");
|
||||
DBUG_ASSERT(unsafe_type == LEX::BINLOG_STMT_UNSAFE_LIMIT);
|
||||
limit_unsafe_warning_count++;
|
||||
ulong count;
|
||||
ulonglong now= my_interval_timer()/1000000000ULL;
|
||||
DBUG_ENTER("protect_against_unsafe_warning_flood");
|
||||
|
||||
count= ++unsafe_warnings_count[unsafe_type];
|
||||
total_unsafe_warnings_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)
|
||||
if (unsafe_suppression_start_time == 0)
|
||||
{
|
||||
limit_unsafe_suppression_start_time= my_interval_timer()/10000000;
|
||||
print_unsafe_warning_to_log(unsafe_type, buf, query);
|
||||
reset_binlog_unsafe_suppression(now);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
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)
|
||||
/*
|
||||
The following is true if we got too many errors or if the error was
|
||||
already suppressed
|
||||
*/
|
||||
if (count >= LIMIT_UNSAFE_WARNING_ACTIVATION_THRESHOLD_COUNT)
|
||||
{
|
||||
ulonglong diff_time= (now - unsafe_suppression_start_time);
|
||||
|
||||
if (!unsafe_warning_suppression_active[unsafe_type])
|
||||
{
|
||||
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 (diff_time <= LIMIT_UNSAFE_WARNING_ACTIVATION_TIMEOUT)
|
||||
{
|
||||
/*
|
||||
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;
|
||||
}
|
||||
unsafe_warning_suppression_active[unsafe_type]= 1;
|
||||
sql_print_information("Suppressing warnings of type '%s' for up to %d seconds because of flooding",
|
||||
ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]),
|
||||
LIMIT_UNSAFE_WARNING_ACTIVATION_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Print the suppression note and the unsafe warning.
|
||||
There is no flooding till now, therefore we restart the monitoring
|
||||
*/
|
||||
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"));
|
||||
}
|
||||
reset_binlog_unsafe_suppression(now);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This type of warnings was suppressed */
|
||||
if (diff_time > LIMIT_UNSAFE_WARNING_ACTIVATION_TIMEOUT)
|
||||
{
|
||||
ulong save_count= total_unsafe_warnings_count;
|
||||
/* Print a suppression note and remove the suppression */
|
||||
reset_binlog_unsafe_suppression(now);
|
||||
sql_print_information("Suppressed %lu unsafe warnings during "
|
||||
"the last %d seconds",
|
||||
save_count, (int) diff_time);
|
||||
}
|
||||
limit_unsafe_warning_count= 0;
|
||||
}
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
DBUG_RETURN(unsafe_warning_suppression_active[unsafe_type]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6108,6 +6119,7 @@ deactivated"));
|
|||
void THD::issue_unsafe_warnings()
|
||||
{
|
||||
char buf[MYSQL_ERRMSG_SIZE * 2];
|
||||
uint32 unsafe_type_flags;
|
||||
DBUG_ENTER("issue_unsafe_warnings");
|
||||
/*
|
||||
Ensure that binlog_unsafe_warning_flags is big enough to hold all
|
||||
|
@ -6115,8 +6127,10 @@ void THD::issue_unsafe_warnings()
|
|||
*/
|
||||
DBUG_ASSERT(LEX::BINLOG_STMT_UNSAFE_COUNT <=
|
||||
sizeof(binlog_unsafe_warning_flags) * CHAR_BIT);
|
||||
|
||||
uint32 unsafe_type_flags= binlog_unsafe_warning_flags;
|
||||
|
||||
if (!(unsafe_type_flags= binlog_unsafe_warning_flags))
|
||||
DBUG_VOID_RETURN; // Nothing to do
|
||||
|
||||
/*
|
||||
For each unsafe_type, check if the statement is unsafe in this way
|
||||
and issue a warning.
|
||||
|
@ -6131,13 +6145,9 @@ void THD::issue_unsafe_warnings()
|
|||
ER_BINLOG_UNSAFE_STATEMENT,
|
||||
ER(ER_BINLOG_UNSAFE_STATEMENT),
|
||||
ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]));
|
||||
if (global_system_variables.log_warnings)
|
||||
{
|
||||
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());
|
||||
}
|
||||
if (global_system_variables.log_warnings > 1 &&
|
||||
!protect_against_unsafe_warning_flood(unsafe_type))
|
||||
print_unsafe_warning_to_log(unsafe_type, buf, query());
|
||||
}
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
|
|
|
@ -2846,7 +2846,7 @@ int add_status_vars(SHOW_VAR *list)
|
|||
{
|
||||
int res= 0;
|
||||
if (status_vars_inited)
|
||||
mysql_mutex_lock(&LOCK_status);
|
||||
mysql_mutex_lock(&LOCK_show_status);
|
||||
if (!all_status_vars.buffer && // array is not allocated yet - do it now
|
||||
my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 200, 20, MYF(0)))
|
||||
{
|
||||
|
@ -2861,7 +2861,7 @@ int add_status_vars(SHOW_VAR *list)
|
|||
sort_dynamic(&all_status_vars, show_var_cmp);
|
||||
err:
|
||||
if (status_vars_inited)
|
||||
mysql_mutex_unlock(&LOCK_status);
|
||||
mysql_mutex_unlock(&LOCK_show_status);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -2923,7 +2923,7 @@ void remove_status_vars(SHOW_VAR *list)
|
|||
{
|
||||
if (status_vars_inited)
|
||||
{
|
||||
mysql_mutex_lock(&LOCK_status);
|
||||
mysql_mutex_lock(&LOCK_show_status);
|
||||
SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
|
||||
|
||||
for (; list->name; list++)
|
||||
|
@ -2944,7 +2944,7 @@ void remove_status_vars(SHOW_VAR *list)
|
|||
}
|
||||
}
|
||||
shrink_var_array(&all_status_vars);
|
||||
mysql_mutex_unlock(&LOCK_status);
|
||||
mysql_mutex_unlock(&LOCK_show_status);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -575,7 +575,6 @@ void mysql_print_status()
|
|||
/* Print key cache status */
|
||||
puts("\nKey caches:");
|
||||
process_key_caches(print_key_cache_status, 0);
|
||||
mysql_mutex_lock(&LOCK_status);
|
||||
printf("\nhandler status:\n\
|
||||
read_key: %10lu\n\
|
||||
read_next: %10lu\n\
|
||||
|
@ -591,7 +590,6 @@ update: %10lu\n",
|
|||
tmp.ha_write_count,
|
||||
tmp.ha_delete_count,
|
||||
tmp.ha_update_count);
|
||||
mysql_mutex_unlock(&LOCK_status);
|
||||
printf("\nTable status:\n\
|
||||
Opened tables: %10lu\n\
|
||||
Open tables: %10lu\n\
|
||||
|
|
Loading…
Reference in a new issue