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 76db74acfa1..cd1ce93177a 100644 --- a/mysql-test/extra/rpl_tests/rpl_truncate_helper.test +++ b/mysql-test/extra/rpl_tests/rpl_truncate_helper.test @@ -1,42 +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; -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; +DROP TABLE t1,t2; +sync_slave_with_master; 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/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/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 1ae98706975..21904fdac51 100644 --- a/mysql-test/suite/rpl/r/rpl_truncate_2myisam.result +++ b/mysql-test/suite/rpl/r/rpl_truncate_2myisam.result @@ -4,241 +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 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; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -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; +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 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; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -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; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -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; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -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; +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 728b8450314..665d0b153e0 100644 --- a/mysql-test/suite/rpl/r/rpl_truncate_3innodb.result +++ b/mysql-test/suite/rpl/r/rpl_truncate_3innodb.result @@ -4,259 +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 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; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -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; +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 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; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -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; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -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; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -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; +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_delete.cc b/sql/sql_delete.cc index b56e042e3d5..b37e2a24895 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) {