diff --git a/mysql-test/suite/binlog/r/binlog_stm_unsafe_warning.result b/mysql-test/suite/binlog/r/binlog_stm_unsafe_warning.result index c2445aa1d1a..e8fd7b82bc4 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_unsafe_warning.result +++ b/mysql-test/suite/binlog/r/binlog_stm_unsafe_warning.result @@ -1,5 +1,6 @@ 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 invokes a trigger or a stored function that inserts into AUTO_INCREMENT column"); ### NOT filtered database => assertion: warnings ARE shown DROP TABLE IF EXISTS t1; CREATE TABLE t1 (a int, b int, primary key (a)); @@ -50,3 +51,29 @@ SET GLOBAL log_warnings = @old_log_warnings; # Count the number of times the "Unsafe" message was printed # to the error log. 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; diff --git a/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test index 35235ce951a..874bb015a07 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test +++ b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test @@ -27,6 +27,7 @@ -- 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 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 @@ -117,3 +118,34 @@ perl; print "Occurrences: $count\n"; close(FILE); 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; diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 92c86cf6e00..f7094e8734d 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -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." 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." -ER_BINLOG_UNSAFE_TWO_AUTOINC_COLUMNS - eng "Statement updates two AUTO_INCREMENT columns. This is unsafe because the generated value cannot be predicted by slave." +ER_BINLOG_UNSAFE_AUTOINC_COLUMNS + 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 eng "Statement uses a UDF. It cannot be determined if the UDF will return the same value on slave." ER_BINLOG_UNSAFE_SYSTEM_VARIABLE diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 31e630d5fea..60be5723559 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -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." 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." -ER_BINLOG_UNSAFE_TWO_AUTOINC_COLUMNS - eng "Statement updates two AUTO_INCREMENT columns. This is unsafe because the generated value cannot be predicted by slave." +ER_BINLOG_UNSAFE_AUTOINC_COLUMNS + 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 eng "Statement uses a UDF. It cannot be determined if the UDF will return the same value on slave." ER_BINLOG_UNSAFE_SYSTEM_VARIABLE diff --git a/sql/sql_base.cc b/sql/sql_base.cc index eb59600b360..e7f014d39a5 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -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 && 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(); } } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 0d423ba85eb..6da734592dc 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -48,7 +48,7 @@ Query_tables_list::binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT] = ER_BINLOG_UNSAFE_LIMIT, ER_BINLOG_UNSAFE_INSERT_DELAYED, ER_BINLOG_UNSAFE_SYSTEM_TABLE, - ER_BINLOG_UNSAFE_TWO_AUTOINC_COLUMNS, + ER_BINLOG_UNSAFE_AUTOINC_COLUMNS, ER_BINLOG_UNSAFE_UDF, ER_BINLOG_UNSAFE_SYSTEM_VARIABLE, ER_BINLOG_UNSAFE_SYSTEM_FUNCTION, diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 800a16cf2b6..923e924dfbc 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1101,13 +1101,15 @@ public: */ BINLOG_STMT_UNSAFE_SYSTEM_TABLE, /** - Update of two autoincrement columns is unsafe. With one - autoincrement column, we store the counter in the binlog so that - slave can restore the correct value. But we can only store one - such counter per statement, so updating more than one - autoincrement column is not safe. + Inserting into an autoincrement column in a stored routine is unsafe. + 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. */ - BINLOG_STMT_UNSAFE_TWO_AUTOINC_COLUMNS, + BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS, /** Using a UDF (user-defined function) is unsafe. */