Current Path : /home/usr.opt/mysql57/mysql-test/suite/rpl/t/ |
FreeBSD hs32.drive.ne.jp 9.1-RELEASE FreeBSD 9.1-RELEASE #1: Wed Jan 14 12:18:08 JST 2015 root@hs32.drive.ne.jp:/sys/amd64/compile/hs32 amd64 |
Current File : //home/usr.opt/mysql57/mysql-test/suite/rpl/t/rpl_begin_commit_rollback.test |
# ==== Purpose ==== # # Test that replication of transaction boundary statements (BEGIN, # COMMIT, and ROLLBACK) works with filters. # # The following properties are tested: # # 1. Transaction boundary statements should never be skipped, even if # filtered out by the slave thread. If they were skipped, a # transaction where the BEGIN is filtered out and the DML is not # filtered out could be executed as a sequence of autocommitted # statements. # # ==== Implementation ==== # # ==== References ==== # # BUG#43263 BEGIN skipped in some replicate-do-db cases # BUG#50407 mysqlbinlog --database=X produces bad output for SAVEPOINTs # BUG#55798 Slave SQL retry on transaction inserts extra data into non-transaction table source include/have_innodb.inc; source include/have_myisam.inc; source include/have_binlog_format_statement.inc; source include/not_gtid_enabled.inc; # UNTIL is not supported by MTS yet (TODO: support and remove the guard) -- source include/not_mts_slave_parallel_workers.inc source include/master-slave.inc; connection slave; call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); connection master; call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); SET @@session.binlog_direct_non_transactional_updates= FALSE; CREATE DATABASE replicate_do_db; CREATE DATABASE binlog_ignore_db; USE replicate_do_db; CREATE TABLE replicate_do_db.t1 (a INT) ENGINE=InnoDB; CREATE TABLE replicate_do_db.t2 (s CHAR(255)) ENGINE=MyISAM; --source include/sync_slave_sql_with_master.inc source include/stop_slave.inc; --source include/rpl_connection_master.inc DELIMITER //; CREATE PROCEDURE replicate_do_db.p1 () BEGIN INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (2); INSERT INTO t1 VALUES (3); INSERT INTO t1 VALUES (4); INSERT INTO t1 VALUES (5); END// CREATE PROCEDURE replicate_do_db.p2 () BEGIN INSERT INTO t1 VALUES (6); INSERT INTO t1 VALUES (7); INSERT INTO t1 VALUES (8); INSERT INTO t1 VALUES (9); INSERT INTO t1 VALUES (10); INSERT INTO t2 VALUES ('executed replicate_do_db.p2()'); END// DELIMITER ;// INSERT INTO replicate_do_db.t2 VALUES ('before call replicate_do_db.p1()'); # Note: the master_log_pos is set to be the position of the BEGIN + 1, # so before fix of BUG#43263 if the BEGIN is ignored, then all the # INSERTS in p1 will be replicated in AUTOCOMMIT=1 mode and the slave # SQL thread will stop right before the first INSERT. After fix of # BUG#43263, BEGIN will not be ignored by the replication db rules, # and then the whole transaction will be executed before slave SQL # stop. --let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1) USE test; BEGIN; CALL replicate_do_db.p1(); COMMIT; # $master_pos is the position after the Gtid/Anonymous event, just # before query_log_event(BEGIN). --let $master_pos= query_get_value(SHOW BINLOG EVENTS FROM $master_pos LIMIT 1, End_log_pos, 1) # $master_pos is one byte into the BEGIN event. # This means START SLAVE UNTIL should skip the entire transaction. --inc $master_pos # The position where the following START SLAVE UNTIL should stop at let $master_end_trans_pos= query_get_value(SHOW MASTER STATUS, Position, 1); INSERT INTO replicate_do_db.t2 VALUES ('after call replicate_do_db.p1()'); SELECT * FROM replicate_do_db.t1; SELECT * FROM replicate_do_db.t2; --source include/rpl_connection_slave.inc replace_result $master_pos MASTER_POS; eval START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=$master_pos; --source include/wait_for_slave_sql_to_stop.inc # Test BUG#43263 --let $assert_cond= [SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1] = $master_end_trans_pos --let $assert_text= Slave should have stopped after executing the stored procedure transaction --source include/assert.inc SELECT * from replicate_do_db.t1; SELECT * from replicate_do_db.t2; --source include/rpl_connection_master.inc INSERT INTO replicate_do_db.t2 VALUES ('before call replicate_do_db.p2()'); # See comments above. --let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1) BEGIN; CALL replicate_do_db.p2(); disable_warnings; ROLLBACK; enable_warnings; --let $master_pos= query_get_value(SHOW BINLOG EVENTS FROM $master_pos LIMIT 1, End_log_pos, 1) --inc $master_pos let $master_end_trans_pos= query_get_value(SHOW MASTER STATUS, Position, 1); INSERT INTO replicate_do_db.t2 VALUES ('after call replicate_do_db.p2()'); SELECT * FROM replicate_do_db.t1; SELECT * FROM replicate_do_db.t2; --source include/rpl_connection_slave.inc --replace_result $master_pos MASTER_POS eval START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=$master_pos; source include/wait_for_slave_sql_to_stop.inc; # Test BUG#43263 --let $assert_cond= [SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1] = $master_end_trans_pos --let $assert_text= Slave should have stopped after executing the stored procedure transaction --source include/assert.inc SELECT * from replicate_do_db.t1; SELECT * from replicate_do_db.t2; START SLAVE; source include/wait_for_slave_sql_to_start.inc; --echo # --echo # SAVEPOINT and ROLLBACK TO have the same problem in BUG#43263 --echo # This was reported by BUG#50407 --source include/rpl_connection_master.inc let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1); BEGIN; INSERT INTO replicate_do_db.t1 VALUES(20); --echo # --echo # Verify whether this statement is binlogged correctly /*comment*/ SAVEPOINT has_comment; USE replicate_do_db; INSERT INTO replicate_do_db.t1 VALUES(30); INSERT INTO replicate_do_db.t2 VALUES("in savepoint has_comment"); USE binlog_ignore_db; SavePoint mixed_cases; USE replicate_do_db; INSERT INTO replicate_do_db.t2 VALUES("in savepoint mixed_cases"); INSERT INTO replicate_do_db.t1 VALUES(40); USE binlog_ignore_db; ROLLBACK TO mixed_cases; ROLLBACK TO has_comment; USE replicate_do_db; INSERT INTO replicate_do_db.t2 VALUES("after rollback to"); INSERT INTO replicate_do_db.t1 VALUES(50); USE binlog_ignore_db; COMMIT; source include/show_binlog_events.inc; --source include/sync_slave_sql_with_master.inc --echo [on slave] --echo # --echo # Verify INSERT statements in savepoints are executed, for MyISAM table --echo # is not effected by ROLLBACK TO SELECT * FROM replicate_do_db.t2 WHERE s LIKE '% savepoint %'; --echo # --echo # Verify INSERT statements on the Innodb table are rolled back; SELECT * FROM replicate_do_db.t1 WHERE a IN (30, 40); --echo --echo # BUG#55798 Slave SQL retry on transaction inserts extra data into --echo # non-transaction table --echo # ---------------------------------------------------------------- --echo # To verify that SQL thread does not retry a transaction which can --echo # not be rolled back safely, even though only a temporary error is --echo # encountered. --echo --source include/rpl_connection_master.inc USE replicate_do_db; DROP TABLE t1, t2; CREATE TABLE t1(c1 INT KEY, c2 CHAR(100)) ENGINE=InnoDB; CREATE TABLE t2(c1 INT) ENGINE=MyISAM; CREATE TABLE t3(c1 INT) ENGINE=InnoDB; INSERT INTO t1 VALUES(1, "master"); SET @@session.binlog_direct_non_transactional_updates= FALSE; --source include/sync_slave_sql_with_master.inc --echo # [ on slave ] USE replicate_do_db; SET @timeout_old= @@GLOBAL.innodb_lock_wait_timeout; SET GLOBAL innodb_lock_wait_timeout= 1; STOP SLAVE SQL_THREAD; source include/wait_for_slave_sql_to_stop.inc; START SLAVE SQL_THREAD; source include/wait_for_slave_sql_to_start.inc; --echo # Verify the SQL thread doesn't retry the transaction when one of --echo # its statements has modified a non-transactional table. --echo # ---------------------------------------------------------------- --echo --echo # INSERT statement inserts a row to a non-transactional table. let $statement= INSERT INTO t2 VALUES(1); source extra/rpl_tests/rpl_temp_error.test; --echo --echo # INSERT ... SELECT statement inserts a row to a non-transactional table. let $statement= INSERT INTO t2 SELECT 2; source extra/rpl_tests/rpl_temp_error.test; --echo --echo # UPDATE statement updates a row to a non-transactional table. connection master; let $statement= UPDATE t2 SET c1= 3; source extra/rpl_tests/rpl_temp_error.test; --echo --echo # MULTI-UPDATE statement updates a row to a non-transactional table. connection master; let $statement= UPDATE t2, t3 SET t2.c1=4, t3.c1= 4; source extra/rpl_tests/rpl_temp_error.test; --echo --echo # DELETE statement deletes a row from a non-transactional table. connection master; let $statement= DELETE FROM t2; source extra/rpl_tests/rpl_temp_error.test; --echo --echo # CREATE TEMPORARY TABLE statement in the transaction let $statement= CREATE TEMPORARY TABLE IF NOT EXISTS temp_t(c1 INT); source extra/rpl_tests/rpl_temp_error.test; --echo --echo # DROP TEMPORARY TABLE statement in the transaction let $statement= DROP TEMPORARY TABLE IF EXISTS temp_t; source extra/rpl_tests/rpl_temp_error.test; --echo --echo # Verify that the SQL thread doesn't retry the transaction if one --echo # of the sub-statements has modified a non-transactional table. --echo # ---------------------------------------------------------------- connection master; --delimiter | CREATE FUNCTION f_insert() RETURNS INT BEGIN INSERT INTO t2 VALUES(1); RETURN 2; END| CREATE FUNCTION f_insert_select() RETURNS INT BEGIN INSERT INTO t2 SELECT 2; RETURN 2; END| CREATE FUNCTION f_update() RETURNS INT BEGIN UPDATE t2 SET c1=3; RETURN 2; END | CREATE TABLE t4 (c1 INT) | INSERT INTO t4 VAlUES(1),(2) | CREATE FUNCTION f_multi_update() RETURNS INT BEGIN UPDATE t2, t4 SET t2.c1=4, t4.c1= 4; RETURN 2; END | CREATE FUNCTION f_delete() RETURNS INT BEGIN DELETE FROM t2; RETURN 2; END | --delimiter ; --echo --echo # The INSERT statement in a function inserts a row into a --echo # non-transactional table. let $statement= INSERT INTO t3 VALUES(f_insert()); source extra/rpl_tests/rpl_temp_error.test; --echo --echo # The INSERT ... SELECT statement in a function inserts a row into a --echo # non-transactional table. let $statement= INSERT INTO t3 VALUES(f_insert()); source extra/rpl_tests/rpl_temp_error.test; --echo --echo # The UPDATE statement in a function updates a row of a --echo # non-transactional table. connection master; let $statement= INSERT INTO t3 VALUES(f_update()); source extra/rpl_tests/rpl_temp_error.test; --echo --echo # The MULTI-UPDATE statement in a function updates a row of a --echo # non-transactional table. connection master; let $statement= INSERT INTO t3 VALUES(f_multi_update()); source extra/rpl_tests/rpl_temp_error.test; --echo --echo # The DELETE statement in a function deletes a row from a --echo # non-transactional table. connection master; let $statement= INSERT INTO t3 VALUES(f_delete()); source extra/rpl_tests/rpl_temp_error.test; SET @@global.innodb_lock_wait_timeout= @timeout_old; --echo # --echo # Clean up --echo # connection master; DROP DATABASE replicate_do_db; DROP DATABASE binlog_ignore_db; --source include/rpl_end.inc