diff --git a/mysql-test/extra/binlog_tests/binlog_truncate.test b/mysql-test/extra/binlog_tests/binlog_truncate.test new file mode 100644 index 00000000000..dce33b3cef0 --- /dev/null +++ b/mysql-test/extra/binlog_tests/binlog_truncate.test @@ -0,0 +1,27 @@ +# BUG #36763: TRUNCATE TABLE fails to replicate when stmt-based +# binlogging is not supported. + +# This should always be logged as a statement, even when executed as a +# row-by-row deletion. + +# $before_truncate A statement to execute (just) before issuing the +# TRUNCATE TABLE + + +eval CREATE TABLE t1 (a INT) ENGINE=$engine; +eval CREATE TABLE t2 (a INT) ENGINE=$engine; +INSERT INTO t2 VALUES (1),(2),(3); +let $binlog_start = query_get_value("SHOW MASTER STATUS", Position, 1); +if (`select length('$before_truncate') > 0`) { + eval $before_truncate; +} +--echo **** Truncate of empty table shall be logged +TRUNCATE TABLE t1; + +if (`select length('$before_truncate') > 0`) { + eval $before_truncate; +} +TRUNCATE TABLE t2; +source include/show_binlog_events.inc; + +DROP TABLE t1,t2; diff --git a/mysql-test/extra/rpl_tests/rpl_truncate.test b/mysql-test/extra/rpl_tests/rpl_truncate.test index bca53336514..7036ab126e1 100644 --- a/mysql-test/extra/rpl_tests/rpl_truncate.test +++ b/mysql-test/extra/rpl_tests/rpl_truncate.test @@ -9,27 +9,8 @@ --source include/master-slave.inc -let $format = STATEMENT; -let $stmt = TRUNCATE TABLE; +let $trunc_stmt = TRUNCATE TABLE; --source extra/rpl_tests/rpl_truncate_helper.test -let $format = MIXED; -let $stmt = TRUNCATE TABLE; +let $trunc_stmt = DELETE FROM; --source extra/rpl_tests/rpl_truncate_helper.test - -let $format = ROW; -let $stmt = TRUNCATE TABLE; ---source extra/rpl_tests/rpl_truncate_helper.test - -let $format = STATEMENT; -let $stmt = DELETE FROM; ---source extra/rpl_tests/rpl_truncate_helper.test - -let $format = MIXED; -let $stmt = DELETE FROM; ---source extra/rpl_tests/rpl_truncate_helper.test - -let $format = ROW; -let $stmt = DELETE FROM; ---source extra/rpl_tests/rpl_truncate_helper.test - diff --git a/mysql-test/extra/rpl_tests/rpl_truncate_helper.test b/mysql-test/extra/rpl_tests/rpl_truncate_helper.test index eb0729e4921..cd1ce93177a 100644 --- a/mysql-test/extra/rpl_tests/rpl_truncate_helper.test +++ b/mysql-test/extra/rpl_tests/rpl_truncate_helper.test @@ -1,47 +1,35 @@ -connection slave; -STOP SLAVE; -source include/wait_for_slave_to_stop.inc; -connection master; ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings -connection slave; ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings -RESET SLAVE; -START SLAVE; +source include/reset_master_and_slave.inc; --echo **** On Master **** connection master; -SET @old_session_binlog_format= @@session.binlog_format; -SET @old_global_binlog_format= @@global.binlog_format; - -eval SET SESSION BINLOG_FORMAT=$format; -eval SET GLOBAL BINLOG_FORMAT=$format; - eval CREATE TABLE t1 (a INT, b LONG) ENGINE=$engine; INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; ---echo **** On Slave **** sync_slave_with_master; -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; --echo **** On Master **** connection master; -eval $stmt t1; -SELECT * FROM t1; ---echo **** On Slave **** +eval $trunc_stmt t1; sync_slave_with_master; -# Should be empty -SELECT * FROM t1; + +let $diff_table_1=master:test.t1; +let $diff_table_2=slave:test.t1; +source include/diff_tables.inc; + +--echo ==== Test using a table with delete triggers ==== --echo **** On Master **** connection master; -DROP TABLE t1; -let $SERVER_VERSION=`select version()`; -source include/show_binlog_events.inc; +SET @count := 1; +eval CREATE TABLE t2 (a INT, b LONG) ENGINE=$engine; +CREATE TRIGGER trg1 BEFORE DELETE ON t1 FOR EACH ROW SET @count := @count + 1; +sync_slave_with_master; +--echo **** On Master **** +connection master; +eval $trunc_stmt t1; +sync_slave_with_master; + +let $diff_table_1=master:test.t2; +let $diff_table_2=slave:test.t2; +source include/diff_tables.inc; connection master; -RESET MASTER; -SET @@session.binlog_format= @old_session_binlog_format; -SET @@global.binlog_format= @old_global_binlog_format; +DROP TABLE t1,t2; +sync_slave_with_master; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 511cd4d07ba..ba426446075 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -45,8 +45,8 @@ BEGIN { print "=======================================================\n"; print " WARNING: Using mysql-test-run.pl version 1! \n"; print "=======================================================\n"; - require "lib/v1/mysql-test-run.pl"; - exit(1); + # Should use exec() here on *nix but this appears not to work on Windows + exit(system($^X, "lib/v1/mysql-test-run.pl", @ARGV) >> 8); } elsif ( $version == 2 ) { diff --git a/mysql-test/suite/binlog/r/binlog_truncate_innodb.result b/mysql-test/suite/binlog/r/binlog_truncate_innodb.result new file mode 100644 index 00000000000..ab237898a74 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_truncate_innodb.result @@ -0,0 +1,63 @@ +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); +**** Truncate of empty table shall be logged +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 +DROP TABLE t1,t2; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +**** Truncate of empty table shall be logged +TRUNCATE TABLE t1; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +TRUNCATE TABLE t2; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 +DROP TABLE t1,t2; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +**** Truncate of empty table shall be logged +TRUNCATE TABLE t1; +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +TRUNCATE TABLE t2; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 +DROP TABLE t1,t2; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); +SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +**** Truncate of empty table shall be logged +TRUNCATE TABLE t1; +SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +TRUNCATE TABLE t2; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 +DROP TABLE t1,t2; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +**** Truncate of empty table shall be logged +TRUNCATE TABLE t1; +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +TRUNCATE TABLE t2; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 +DROP TABLE t1,t2; diff --git a/mysql-test/suite/binlog/r/binlog_truncate_myisam.result b/mysql-test/suite/binlog/r/binlog_truncate_myisam.result new file mode 100644 index 00000000000..544882c2c9b --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_truncate_myisam.result @@ -0,0 +1,11 @@ +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +CREATE TABLE t2 (a INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1),(2),(3); +**** Truncate of empty table shall be logged +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 +DROP TABLE t1,t2; diff --git a/mysql-test/suite/binlog/r/binlog_unsafe.result b/mysql-test/suite/binlog/r/binlog_unsafe.result index 1f7b217dc31..7c0980ba77c 100644 --- a/mysql-test/suite/binlog/r/binlog_unsafe.result +++ b/mysql-test/suite/binlog/r/binlog_unsafe.result @@ -220,3 +220,10 @@ Warning 1592 Statement is not safe to log in statement format. Warning 1592 Statement is not safe to log in statement format. DROP PROCEDURE p1; DROP TABLE t1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a VARCHAR(100), b VARCHAR(100)); +INSERT INTO t1 VALUES ('a','b'); +UPDATE t1 SET b = '%s%s%s%s%s%s%s%s%s%s%s%s%s%s' WHERE a = 'a' LIMIT 1; +Warnings: +Warning 1592 Statement is not safe to log in statement format. +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_truncate_innodb-master.opt b/mysql-test/suite/binlog/t/binlog_truncate_innodb-master.opt new file mode 100644 index 00000000000..69cc489a969 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_truncate_innodb-master.opt @@ -0,0 +1 @@ +--loose-innodb \ No newline at end of file diff --git a/mysql-test/suite/binlog/t/binlog_truncate_innodb.test b/mysql-test/suite/binlog/t/binlog_truncate_innodb.test new file mode 100644 index 00000000000..9695710377e --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_truncate_innodb.test @@ -0,0 +1,22 @@ +source include/have_log_bin.inc; +source include/have_innodb.inc; + +let $engine = InnoDB; +source extra/binlog_tests/binlog_truncate.test; + +# Under transaction isolation level READ UNCOMMITTED and READ +# COMMITTED, InnoDB does not permit statement-based replication of +# row-deleting statement. In these cases, TRUNCATE TABLE should still +# be replicated as a statement. + +let $before_truncate = SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +source extra/binlog_tests/binlog_truncate.test; + +let $before_truncate = SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +source extra/binlog_tests/binlog_truncate.test; + +let $before_truncate = SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +source extra/binlog_tests/binlog_truncate.test; + +let $before_truncate = SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +source extra/binlog_tests/binlog_truncate.test; diff --git a/mysql-test/suite/binlog/t/binlog_truncate_myisam.test b/mysql-test/suite/binlog/t/binlog_truncate_myisam.test new file mode 100644 index 00000000000..994647ab78a --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_truncate_myisam.test @@ -0,0 +1,4 @@ +source include/have_log_bin.inc; + +let $engine = MyISAM; +source extra/binlog_tests/binlog_truncate.test; diff --git a/mysql-test/suite/binlog/t/binlog_unsafe.test b/mysql-test/suite/binlog/t/binlog_unsafe.test index 0d7059bc31f..f58233d4fef 100644 --- a/mysql-test/suite/binlog/t/binlog_unsafe.test +++ b/mysql-test/suite/binlog/t/binlog_unsafe.test @@ -257,3 +257,17 @@ delimiter ;| CALL p1(); DROP PROCEDURE p1; DROP TABLE t1; + +# +# Bug#42634: % character in query can cause mysqld signal 11 segfault +# + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (a VARCHAR(100), b VARCHAR(100)); +INSERT INTO t1 VALUES ('a','b'); +UPDATE t1 SET b = '%s%s%s%s%s%s%s%s%s%s%s%s%s%s' WHERE a = 'a' LIMIT 1; +DROP TABLE t1; + diff --git a/mysql-test/suite/binlog/t/disabled.def b/mysql-test/suite/binlog/t/disabled.def index 888298bbb09..0018387de94 100644 --- a/mysql-test/suite/binlog/t/disabled.def +++ b/mysql-test/suite/binlog/t/disabled.def @@ -9,3 +9,5 @@ # Do not use any TAB characters for whitespace. # ############################################################################## +binlog_truncate_innodb : BUG#42643 2009-02-06 mats Changes to InnoDB requires to complete fix for BUG#36763 + diff --git a/mysql-test/suite/rpl/r/rpl_truncate_2myisam.result b/mysql-test/suite/rpl/r/rpl_truncate_2myisam.result index 92e13064856..21904fdac51 100644 --- a/mysql-test/suite/rpl/r/rpl_truncate_2myisam.result +++ b/mysql-test/suite/rpl/r/rpl_truncate_2myisam.result @@ -4,265 +4,43 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +**** Resetting master and slave **** STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; RESET SLAVE; +RESET MASTER; START SLAVE; **** On Master **** -SET @old_session_binlog_format= @@session.binlog_format; -SET @old_global_binlog_format= @@global.binlog_format; -SET SESSION BINLOG_FORMAT=STATEMENT; -SET GLOBAL BINLOG_FORMAT=STATEMENT; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 **** On Master **** TRUNCATE TABLE t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b +Comparing tables master:test.t1 and slave:test.t1 +==== Test using a table with delete triggers ==== **** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM -master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2) -master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -SET @@session.binlog_format= @old_session_binlog_format; -SET @@global.binlog_format= @old_global_binlog_format; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -SET @old_session_binlog_format= @@session.binlog_format; -SET @old_global_binlog_format= @@global.binlog_format; -SET SESSION BINLOG_FORMAT=MIXED; -SET GLOBAL BINLOG_FORMAT=MIXED; -CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; -INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 +SET @count := 1; +CREATE TABLE t2 (a INT, b LONG) ENGINE=MyISAM; +CREATE TRIGGER trg1 BEFORE DELETE ON t1 FOR EACH ROW SET @count := @count + 1; **** On Master **** TRUNCATE TABLE t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b -**** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM -master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2) -master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -SET @@session.binlog_format= @old_session_binlog_format; -SET @@global.binlog_format= @old_global_binlog_format; +Comparing tables master:test.t2 and slave:test.t2 +DROP TABLE t1,t2; +**** Resetting master and slave **** STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; RESET SLAVE; +RESET MASTER; START SLAVE; **** On Master **** -SET @old_session_binlog_format= @@session.binlog_format; -SET @old_global_binlog_format= @@global.binlog_format; -SET SESSION BINLOG_FORMAT=ROW; -SET GLOBAL BINLOG_FORMAT=ROW; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 -**** On Master **** -TRUNCATE TABLE t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b -**** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Query # # use `test`; COMMIT -master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -SET @@session.binlog_format= @old_session_binlog_format; -SET @@global.binlog_format= @old_global_binlog_format; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -SET @old_session_binlog_format= @@session.binlog_format; -SET @old_global_binlog_format= @@global.binlog_format; -SET SESSION BINLOG_FORMAT=STATEMENT; -SET GLOBAL BINLOG_FORMAT=STATEMENT; -CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; -INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 **** On Master **** DELETE FROM t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b +Comparing tables master:test.t1 and slave:test.t1 +==== Test using a table with delete triggers ==== **** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM -master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2) -master-bin.000001 # Query # # use `test`; DELETE FROM t1 -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -SET @@session.binlog_format= @old_session_binlog_format; -SET @@global.binlog_format= @old_global_binlog_format; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -SET @old_session_binlog_format= @@session.binlog_format; -SET @old_global_binlog_format= @@global.binlog_format; -SET SESSION BINLOG_FORMAT=MIXED; -SET GLOBAL BINLOG_FORMAT=MIXED; -CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; -INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 +SET @count := 1; +CREATE TABLE t2 (a INT, b LONG) ENGINE=MyISAM; +CREATE TRIGGER trg1 BEFORE DELETE ON t1 FOR EACH ROW SET @count := @count + 1; **** On Master **** DELETE FROM t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b -**** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM -master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2) -master-bin.000001 # Query # # use `test`; DELETE FROM t1 -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -SET @@session.binlog_format= @old_session_binlog_format; -SET @@global.binlog_format= @old_global_binlog_format; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -SET @old_session_binlog_format= @@session.binlog_format; -SET @old_global_binlog_format= @@global.binlog_format; -SET SESSION BINLOG_FORMAT=ROW; -SET GLOBAL BINLOG_FORMAT=ROW; -CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; -INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 -**** On Master **** -DELETE FROM t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b -3 3 -**** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Query # # use `test`; COMMIT -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Delete_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Query # # use `test`; COMMIT -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -SET @@session.binlog_format= @old_session_binlog_format; -SET @@global.binlog_format= @old_global_binlog_format; +Comparing tables master:test.t2 and slave:test.t2 +DROP TABLE t1,t2; diff --git a/mysql-test/suite/rpl/r/rpl_truncate_3innodb.result b/mysql-test/suite/rpl/r/rpl_truncate_3innodb.result index 94461c33c46..665d0b153e0 100644 --- a/mysql-test/suite/rpl/r/rpl_truncate_3innodb.result +++ b/mysql-test/suite/rpl/r/rpl_truncate_3innodb.result @@ -4,283 +4,43 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +**** Resetting master and slave **** STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; RESET SLAVE; +RESET MASTER; START SLAVE; **** On Master **** -SET @old_session_binlog_format= @@session.binlog_format; -SET @old_global_binlog_format= @@global.binlog_format; -SET SESSION BINLOG_FORMAT=STATEMENT; -SET GLOBAL BINLOG_FORMAT=STATEMENT; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 **** On Master **** TRUNCATE TABLE t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b +Comparing tables master:test.t1 and slave:test.t1 +==== Test using a table with delete triggers ==== **** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2) -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -SET @@session.binlog_format= @old_session_binlog_format; -SET @@global.binlog_format= @old_global_binlog_format; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -SET @old_session_binlog_format= @@session.binlog_format; -SET @old_global_binlog_format= @@global.binlog_format; -SET SESSION BINLOG_FORMAT=MIXED; -SET GLOBAL BINLOG_FORMAT=MIXED; -CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 +SET @count := 1; +CREATE TABLE t2 (a INT, b LONG) ENGINE=InnoDB; +CREATE TRIGGER trg1 BEFORE DELETE ON t1 FOR EACH ROW SET @count := @count + 1; **** On Master **** TRUNCATE TABLE t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b -**** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2) -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -SET @@session.binlog_format= @old_session_binlog_format; -SET @@global.binlog_format= @old_global_binlog_format; +Comparing tables master:test.t2 and slave:test.t2 +DROP TABLE t1,t2; +**** Resetting master and slave **** STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; RESET SLAVE; +RESET MASTER; START SLAVE; **** On Master **** -SET @old_session_binlog_format= @@session.binlog_format; -SET @old_global_binlog_format= @@global.binlog_format; -SET SESSION BINLOG_FORMAT=ROW; -SET GLOBAL BINLOG_FORMAT=ROW; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 -**** On Master **** -TRUNCATE TABLE t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b -**** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -SET @@session.binlog_format= @old_session_binlog_format; -SET @@global.binlog_format= @old_global_binlog_format; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -SET @old_session_binlog_format= @@session.binlog_format; -SET @old_global_binlog_format= @@global.binlog_format; -SET SESSION BINLOG_FORMAT=STATEMENT; -SET GLOBAL BINLOG_FORMAT=STATEMENT; -CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 **** On Master **** DELETE FROM t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b +Comparing tables master:test.t1 and slave:test.t1 +==== Test using a table with delete triggers ==== **** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2) -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; DELETE FROM t1 -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -SET @@session.binlog_format= @old_session_binlog_format; -SET @@global.binlog_format= @old_global_binlog_format; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -SET @old_session_binlog_format= @@session.binlog_format; -SET @old_global_binlog_format= @@global.binlog_format; -SET SESSION BINLOG_FORMAT=MIXED; -SET GLOBAL BINLOG_FORMAT=MIXED; -CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 +SET @count := 1; +CREATE TABLE t2 (a INT, b LONG) ENGINE=InnoDB; +CREATE TRIGGER trg1 BEFORE DELETE ON t1 FOR EACH ROW SET @count := @count + 1; **** On Master **** DELETE FROM t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b -**** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2) -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; DELETE FROM t1 -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -SET @@session.binlog_format= @old_session_binlog_format; -SET @@global.binlog_format= @old_global_binlog_format; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -SET @old_session_binlog_format= @@session.binlog_format; -SET @old_global_binlog_format= @@global.binlog_format; -SET SESSION BINLOG_FORMAT=ROW; -SET GLOBAL BINLOG_FORMAT=ROW; -CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 -**** On Master **** -DELETE FROM t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b -3 3 -**** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Delete_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -SET @@session.binlog_format= @old_session_binlog_format; -SET @@global.binlog_format= @old_global_binlog_format; +Comparing tables master:test.t2 and slave:test.t2 +DROP TABLE t1,t2; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 6db9f1df0f2..d17bf085e3b 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5103,8 +5103,15 @@ int decide_logging_format(THD *thd, TABLE_LIST *tables) { if (mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG)) { - handler::Table_flags flags_some_set= handler::Table_flags(); - handler::Table_flags flags_all_set= ~handler::Table_flags(); + /* + Compute the starting vectors for the computations by creating a + set with all the capabilities bits set and one with no + capabilities bits set. + */ + handler::Table_flags flags_some_set= 0; + handler::Table_flags flags_all_set= + HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE; + my_bool multi_engine= FALSE; void* prev_ht= NULL; for (TABLE_LIST *table= tables; table; table= table->next_global) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 06f1c644be0..118dc5af68f 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -3660,16 +3660,14 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg, if (lex->is_stmt_unsafe() && variables.binlog_format == BINLOG_FORMAT_STMT) { - DBUG_ASSERT(this->query != NULL); push_warning(this, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BINLOG_UNSAFE_STATEMENT, ER(ER_BINLOG_UNSAFE_STATEMENT)); if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED)) { - char warn_buf[MYSQL_ERRMSG_SIZE]; - my_snprintf(warn_buf, MYSQL_ERRMSG_SIZE, "%s Statement: %s", - ER(ER_BINLOG_UNSAFE_STATEMENT), this->query); - sql_print_warning(warn_buf); + sql_print_warning("%s Statement: %.*s", + ER(ER_BINLOG_UNSAFE_STATEMENT), + MYSQL_ERRMSG_SIZE, query_arg); binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED; } } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 1a23077f6a0..d87eafa3e0c 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -51,6 +51,11 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, THD::killed_state killed_status= THD::NOT_KILLED; DBUG_ENTER("mysql_delete"); + THD::enum_binlog_query_type query_type= + thd->lex->sql_command == SQLCOM_TRUNCATE ? + THD::STMT_QUERY_TYPE : + THD::ROW_QUERY_TYPE; + if (open_and_lock_tables(thd, table_list)) DBUG_RETURN(TRUE); if (!(table= table_list->table)) @@ -135,6 +140,11 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, DBUG_PRINT("debug", ("Trying to use delete_all_rows()")); if (!(error=table->file->ha_delete_all_rows())) { + /* + If delete_all_rows() is used, it is not possible to log the + query in row format, so we have to log it in statement format. + */ + query_type= THD::STMT_QUERY_TYPE; error= -1; // ok deleted= maybe_deleted; goto cleanup; @@ -374,6 +384,11 @@ cleanup: { if (mysql_bin_log.is_open()) { + bool const is_trans= + thd->lex->sql_command == SQLCOM_TRUNCATE ? + FALSE : + transactional_table; + if (error < 0) thd->clear_error(); /* @@ -381,10 +396,13 @@ cleanup: storage engine does not inject the rows itself, we replicate statement-based; otherwise, 'ha_delete_row()' was used to delete specific rows which we might log row-based. + + Note that TRUNCATE TABLE is not transactional and should + therefore be treated as a DDL. */ - int log_result= thd->binlog_query(THD::ROW_QUERY_TYPE, + int log_result= thd->binlog_query(query_type, thd->query, thd->query_length, - transactional_table, FALSE, killed_status); + is_trans, FALSE, killed_status); if (log_result && transactional_table) {