Commit 8d240586 authored by Andrei Elkin's avatar Andrei Elkin

Bug #50192 Strange effect in replication test, trigger, auto_increment

The auto-inc unsafe warning makes sense even though it's just
one auto-inc table could be involved via a trigger or a stored
function.
However its content was not updated by bug@45677 fixes continuing to mention
two tables whereas the fixes refined semantics of replication of auto_increment 
in stored routine.

Fixed with updating the error message, renaming the error and an internal unsafe-condition 
constants.

A documentation notice
======================

      Inserting into an autoincrement column in a stored function or a trigger
      is unsafe for replication.
      Even with just one autoincrement column, if the routine is invoked more than 
      once slave is not guaranteed to execute the statement graph same way as 
      the master.
      And since it's impossible to estimate how many times a routine can be invoked at 
      the query pre-execution phase (see lock_tables), the statement is marked
      pessimistically unsafe. 



mysql-test/suite/binlog/r/binlog_stm_unsafe_warning.result:
  results updated to include the expected unsafe warning.
mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test:
  regression test for bug#50192 to diplaying the unsafe warning comes out to the user warning stack.
sql/share/errmsg-utf8.txt:
  Updating the auto-inc unsafe message to correspond to bug@45677 fixes' new sematics.
sql/share/errmsg.txt:
  Updating the auto-inc unsafe message to correspond to bug@45677 fixes' new sematics.
sql/sql_base.cc:
  changing a symbolic name to correspond to updated by bug@45677 fixes new sematics.
sql/sql_lex.cc:
  changing a symbolic name to correspond to updated by bug@45677 fixes new sematics.
sql/sql_lex.h:
  changing a symbolic name to correspond to updated by bug@45677 fixes new sematics
  and description comments.
parent 827a0d7c
call mtr.add_suppression("Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. .*"); call mtr.add_suppression("Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. .*");
call mtr.add_suppression("Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave. .*"); call mtr.add_suppression("Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave. .*");
call mtr.add_suppression("Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement invokes a trigger or a stored function that inserts into AUTO_INCREMENT column");
### NOT filtered database => assertion: warnings ARE shown ### NOT filtered database => assertion: warnings ARE shown
DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (a int, b int, primary key (a)); CREATE TABLE t1 (a int, b int, primary key (a));
...@@ -50,3 +51,29 @@ SET GLOBAL log_warnings = @old_log_warnings; ...@@ -50,3 +51,29 @@ SET GLOBAL log_warnings = @old_log_warnings;
# Count the number of times the "Unsafe" message was printed # Count the number of times the "Unsafe" message was printed
# to the error log. # to the error log.
Occurrences: 1 Occurrences: 1
DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1 (a int);
CREATE TABLE t2 (a int auto_increment primary key, b int);
CREATE TRIGGER tr_bug50192 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t2 (b) VALUES (1);
CREATE FUNCTION sf_bug50192() RETURNS INTEGER
BEGIN
INSERT INTO t2(b) VALUES(2);
RETURN 1;
END |
INSERT INTO t1 VALUES (0);
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement invokes a trigger or a stored function that inserts into AUTO_INCREMENT column which is unsafe to binlog in STATEMENT format because slave may execute it non-deterministically.
SHOW WARNINGS;
Level Code Message
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement invokes a trigger or a stored function that inserts into AUTO_INCREMENT column which is unsafe to binlog in STATEMENT format because slave may execute it non-deterministically.
SELECT sf_bug50192();
sf_bug50192()
1
Warnings:
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement invokes a trigger or a stored function that inserts into AUTO_INCREMENT column which is unsafe to binlog in STATEMENT format because slave may execute it non-deterministically.
SHOW WARNINGS;
Level Code Message
Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement invokes a trigger or a stored function that inserts into AUTO_INCREMENT column which is unsafe to binlog in STATEMENT format because slave may execute it non-deterministically.
DROP FUNCTION sf_bug50192;
DROP TRIGGER tr_bug50192;
DROP TABLE t1, t2;
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
-- source include/have_binlog_format_statement.inc -- source include/have_binlog_format_statement.inc
call mtr.add_suppression("Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. .*"); call mtr.add_suppression("Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. .*");
call mtr.add_suppression("Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave. .*"); call mtr.add_suppression("Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave. .*");
call mtr.add_suppression("Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement invokes a trigger or a stored function that inserts into AUTO_INCREMENT column");
-- echo ### NOT filtered database => assertion: warnings ARE shown -- echo ### NOT filtered database => assertion: warnings ARE shown
...@@ -117,3 +118,34 @@ perl; ...@@ -117,3 +118,34 @@ perl;
print "Occurrences: $count\n"; print "Occurrences: $count\n";
close(FILE); close(FILE);
EOF EOF
# bug#50192: diplaying the unsafe warning comes out to the user warning stack
-- disable_warnings
DROP TABLE IF EXISTS t1, t2;
-- enable_warnings
CREATE TABLE t1 (a int);
CREATE TABLE t2 (a int auto_increment primary key, b int);
CREATE TRIGGER tr_bug50192 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t2 (b) VALUES (1);
DELIMITER |;
CREATE FUNCTION sf_bug50192() RETURNS INTEGER
BEGIN
INSERT INTO t2(b) VALUES(2);
RETURN 1;
END |
DELIMITER ;|
INSERT INTO t1 VALUES (0);
SHOW WARNINGS;
SELECT sf_bug50192();
SHOW WARNINGS;
# cleanup
DROP FUNCTION sf_bug50192;
DROP TRIGGER tr_bug50192;
DROP TABLE t1, t2;
...@@ -6280,8 +6280,8 @@ ER_BINLOG_UNSAFE_INSERT_DELAYED ...@@ -6280,8 +6280,8 @@ ER_BINLOG_UNSAFE_INSERT_DELAYED
eng "Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted." eng "Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted."
ER_BINLOG_UNSAFE_SYSTEM_TABLE ER_BINLOG_UNSAFE_SYSTEM_TABLE
eng "Statement uses the general_log, slow_log or performance_schema table(s). This is unsafe because system tables may differ on slave." eng "Statement uses the general_log, slow_log or performance_schema table(s). This is unsafe because system tables may differ on slave."
ER_BINLOG_UNSAFE_TWO_AUTOINC_COLUMNS ER_BINLOG_UNSAFE_AUTOINC_COLUMNS
eng "Statement updates two AUTO_INCREMENT columns. This is unsafe because the generated value cannot be predicted by slave." eng "Statement invokes a trigger or a stored function that inserts into AUTO_INCREMENT column which is unsafe to binlog in STATEMENT format because slave may execute it non-deterministically."
ER_BINLOG_UNSAFE_UDF ER_BINLOG_UNSAFE_UDF
eng "Statement uses a UDF. It cannot be determined if the UDF will return the same value on slave." eng "Statement uses a UDF. It cannot be determined if the UDF will return the same value on slave."
ER_BINLOG_UNSAFE_SYSTEM_VARIABLE ER_BINLOG_UNSAFE_SYSTEM_VARIABLE
......
...@@ -6221,8 +6221,8 @@ ER_BINLOG_UNSAFE_INSERT_DELAYED ...@@ -6221,8 +6221,8 @@ ER_BINLOG_UNSAFE_INSERT_DELAYED
eng "Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted." eng "Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted."
ER_BINLOG_UNSAFE_SYSTEM_TABLE ER_BINLOG_UNSAFE_SYSTEM_TABLE
eng "Statement uses the general_log, slow_log or performance_schema table(s). This is unsafe because system tables may differ on slave." eng "Statement uses the general_log, slow_log or performance_schema table(s). This is unsafe because system tables may differ on slave."
ER_BINLOG_UNSAFE_TWO_AUTOINC_COLUMNS ER_BINLOG_UNSAFE_AUTOINC_COLUMNS
eng "Statement updates two AUTO_INCREMENT columns. This is unsafe because the generated value cannot be predicted by slave." eng "Statement invokes a trigger or a stored function that inserts into AUTO_INCREMENT column which is unsafe to binlog in STATEMENT format because slave may execute it non-deterministically."
ER_BINLOG_UNSAFE_UDF ER_BINLOG_UNSAFE_UDF
eng "Statement uses a UDF. It cannot be determined if the UDF will return the same value on slave." eng "Statement uses a UDF. It cannot be determined if the UDF will return the same value on slave."
ER_BINLOG_UNSAFE_SYSTEM_VARIABLE ER_BINLOG_UNSAFE_SYSTEM_VARIABLE
......
...@@ -5181,7 +5181,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) ...@@ -5181,7 +5181,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables && if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables &&
has_write_table_with_auto_increment(thd->lex->first_not_own_table())) has_write_table_with_auto_increment(thd->lex->first_not_own_table()))
{ {
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_TWO_AUTOINC_COLUMNS); thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS);
thd->set_current_stmt_binlog_format_row_if_mixed(); thd->set_current_stmt_binlog_format_row_if_mixed();
} }
} }
......
...@@ -48,7 +48,7 @@ Query_tables_list::binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT] = ...@@ -48,7 +48,7 @@ Query_tables_list::binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT] =
ER_BINLOG_UNSAFE_LIMIT, ER_BINLOG_UNSAFE_LIMIT,
ER_BINLOG_UNSAFE_INSERT_DELAYED, ER_BINLOG_UNSAFE_INSERT_DELAYED,
ER_BINLOG_UNSAFE_SYSTEM_TABLE, ER_BINLOG_UNSAFE_SYSTEM_TABLE,
ER_BINLOG_UNSAFE_TWO_AUTOINC_COLUMNS, ER_BINLOG_UNSAFE_AUTOINC_COLUMNS,
ER_BINLOG_UNSAFE_UDF, ER_BINLOG_UNSAFE_UDF,
ER_BINLOG_UNSAFE_SYSTEM_VARIABLE, ER_BINLOG_UNSAFE_SYSTEM_VARIABLE,
ER_BINLOG_UNSAFE_SYSTEM_FUNCTION, ER_BINLOG_UNSAFE_SYSTEM_FUNCTION,
......
...@@ -1101,13 +1101,15 @@ class Query_tables_list ...@@ -1101,13 +1101,15 @@ class Query_tables_list
*/ */
BINLOG_STMT_UNSAFE_SYSTEM_TABLE, BINLOG_STMT_UNSAFE_SYSTEM_TABLE,
/** /**
Update of two autoincrement columns is unsafe. With one Inserting into an autoincrement column in a stored routine is unsafe.
autoincrement column, we store the counter in the binlog so that Even with just one autoincrement column, if the routine is invoked more than
slave can restore the correct value. But we can only store one once slave is not guaranteed to execute the statement graph same way as
such counter per statement, so updating more than one the master.
autoincrement column is not safe. And since it's impossible to estimate how many times a routine can be invoked at
*/ the query pre-execution phase (see lock_tables), the statement is marked
BINLOG_STMT_UNSAFE_TWO_AUTOINC_COLUMNS, pessimistically unsafe.
*/
BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS,
/** /**
Using a UDF (user-defined function) is unsafe. Using a UDF (user-defined function) is unsafe.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment