diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result index c6ee170eef7..9b66ddb37b4 100644 --- a/mysql-test/r/multi_update.result +++ b/mysql-test/r/multi_update.result @@ -1,3 +1,4 @@ +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); drop table if exists t1,t2,t3; drop database if exists mysqltest; drop view if exists v1; @@ -125,6 +126,8 @@ ID ParId tst tst1 2 2 NULL NULL 3 3 NULL NULL UPDATE t2, t1 SET t2.tst = t1.tst, t2.tst1 = t1.tst1 WHERE t2.ParId = t1.Id; +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave. select * from t2; ID ParId tst tst1 1 1 MySQL MySQL AB @@ -349,6 +352,8 @@ drop table t1,t2; create table t1 (a int not null auto_increment primary key, b int not null); insert into t1 (b) values (1),(2),(3),(4); update t1, t1 as t2 set t1.b=t2.b+1 where t1.a=t2.a; +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave. select * from t1; a b 1 2 @@ -605,7 +610,8 @@ a b show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # BEGIN -master-bin.000001 # Query # # use `test`; UPDATE t2,t1 SET t2.a=t1.a+2 +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Update_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # COMMIT delete from t1; delete from t2; @@ -617,7 +623,8 @@ ERROR 23000: Duplicate entry '4' for key 'PRIMARY' show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # BEGIN -master-bin.000001 # Query # # use `test`; UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Update_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # COMMIT drop table t1, t2; set @@session.binlog_format= @sav_binlog_format; diff --git a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result index d89bce479e5..193172912be 100644 --- a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result +++ b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result @@ -861,7 +861,8 @@ master-bin.000001 # Table_map # # table_id: # (test_rpl.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Xid # # COMMIT /* XID */ master-bin.000001 # Query # # BEGIN -master-bin.000001 # Query # # use `test_rpl`; INSERT INTO t2 SELECT * FROM t1 +master-bin.000001 # Table_map # # table_id: # (test_rpl.t2) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Xid # # COMMIT /* XID */ master-bin.000001 # Query # # BEGIN master-bin.000001 # Query # # use `test_rpl`; INSERT INTO t2 VALUES (1, 't1, text 1') ON DUPLICATE KEY UPDATE b = 't2, text 1' diff --git a/mysql-test/suite/rpl/r/rpl_known_bugs_detection.result b/mysql-test/suite/rpl/r/rpl_known_bugs_detection.result index 8ed402b9f8d..295ce7f5889 100644 --- a/mysql-test/suite/rpl/r/rpl_known_bugs_detection.result +++ b/mysql-test/suite/rpl/r/rpl_known_bugs_detection.result @@ -45,6 +45,7 @@ ON DUPLICATE KEY UPDATE t1.field_3 = t2.field_c; Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... SELECT... ON DUPLICATE KEY UPDATE is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are updated. This order cannot be predicted and may differ on master and the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave. INSERT INTO t2 (field_a, field_b, field_c) VALUES (6, 'f', '6f'); INSERT INTO t1 (field_1, field_2, field_3) SELECT t2.field_a, t2.field_b, t2.field_c @@ -53,6 +54,7 @@ ON DUPLICATE KEY UPDATE t1.field_3 = t2.field_c; Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... SELECT... ON DUPLICATE KEY UPDATE is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are updated. This order cannot be predicted and may differ on master and the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave. SELECT * FROM t1; id field_1 field_2 field_3 1 1 a 1a diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test index 99ffe278e44..6742b2c7b94 100644 --- a/mysql-test/t/multi_update.test +++ b/mysql-test/t/multi_update.test @@ -6,6 +6,8 @@ source include/not_embedded.inc; source include/have_log_bin.inc; +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); + --disable_warnings drop table if exists t1,t2,t3; drop database if exists mysqltest; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index f4776130d2f..c5b1ffb1fa9 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5681,20 +5681,20 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, *(ptr++)= table->table; } + /* + DML statements that modify a table with an auto_increment column based on + rows selected from a table are unsafe as the order in which the rows are + fetched fron the select tables cannot be determined and may differ on + master and slave. + */ + if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables && + has_write_table_with_auto_increment_and_select(tables)) + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT); + /* We have to emulate LOCK TABLES if we are statement needs prelocking. */ if (thd->lex->requires_prelocking()) { - /* - DML statements that modify a table with an auto_increment column based on - rows selected from a table are unsafe as the order in which the rows are - fetched fron the select tables cannot be determined and may differ on - master and slave. - */ - if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables && - has_write_table_with_auto_increment_and_select(tables)) - thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT); - /* A query that modifies autoinc column in sub-statement can make the master and slave inconsistent. @@ -9093,7 +9093,7 @@ has_write_table_with_auto_increment(TABLE_LIST *tables) } /* - checks if the tables have select tables in the table list and write tables + checks if we have select tables in the table list and write tables with auto-increment column. SYNOPSIS