--source include/have_innodb.inc --source include/have_debug.inc --source include/have_debug_sync.inc --source include/have_binlog_format_statement.inc --let $rpl_topology=1->2 --source include/rpl_init.inc --echo *** Test killing transaction waiting in commit for previous transaction to commit, when not using 2-phase commit *** --connection server_2 SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; --source include/stop_slave.inc SET GLOBAL slave_parallel_threads=10; CHANGE MASTER TO master_use_gtid=slave_pos; --source include/start_slave.inc --connection server_1 ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; # Use a stored function to inject a debug_sync into the appropriate THD. # The function does nothing on the master, and on the slave it injects the # desired debug_sync action(s). SET sql_log_bin=0; --delimiter || CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500)) RETURNS INT DETERMINISTIC BEGIN RETURN x; END || --delimiter ; SET sql_log_bin=1; CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; --save_master_pos --connection server_2 SET sql_log_bin=0; --delimiter || CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500)) RETURNS INT DETERMINISTIC BEGIN IF d1 != '' THEN SET debug_sync = d1; END IF; IF d2 != '' THEN SET debug_sync = d2; END IF; RETURN x; END || --delimiter ; SET sql_log_bin=1; --sync_with_master # Set up three transactions on the master that will be group-committed # together so they can be replicated in parallel on the slave. --connect (con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,) SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1'; SET binlog_format=statement; SET debug_dbug='+d,row_ins_row_level'; send INSERT INTO t3 VALUES (31, foo(31, 'ha_commit_one_phase WAIT_FOR t2_waiting', 'commit_one_phase_2 SIGNAL t1_ready WAIT_FOR t1_cont')); --connection server_1 SET debug_sync='now WAIT_FOR master_queued1'; --connect (con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,) SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2'; SET binlog_format=statement; SET debug_dbug='+d,row_ins_row_level'; BEGIN; # This insert is just so we can get T2 to wait while a query is running that we # can see in SHOW PROCESSLIST so we can get its thread_id to kill later. INSERT INTO t3 VALUES (32, foo(32, 'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont', '')); # This insert sets up debug_sync points so that T2 will tell when it is at its # wait point where we want to kill it - and when it has been killed. INSERT INTO t3 VALUES (33, foo(33, 'wait_for_prior_commit_waiting SIGNAL t2_waiting', 'wait_for_prior_commit_killed SIGNAL t2_killed')); send COMMIT; --connection server_1 SET debug_sync='now WAIT_FOR master_queued2'; --connect (con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,) SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3'; SET binlog_format=statement; SET debug_dbug='+d,row_ins_row_level'; send INSERT INTO t3 VALUES (34, foo(34, '', '')); --connection server_1 SET debug_sync='now WAIT_FOR master_queued3'; SET debug_sync='now SIGNAL master_cont1'; --connection con_temp3 REAP; --connection con_temp4 REAP; --connection con_temp5 REAP; --connection server_1 SELECT * FROM t3 WHERE a >= 30 ORDER BY a; --connection server_2 SET sql_log_bin=0; CALL mtr.add_suppression("Query execution was interrupted"); CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends"); CALL mtr.add_suppression("Slave: Connection was killed"); SET sql_log_bin=1; # Wait until T2 is inside executing its insert of 32, then find it in SHOW # PROCESSLIST to know its thread id for KILL later. SET debug_sync='now WAIT_FOR t2_query'; --let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(32%' AND INFO NOT LIKE '%LIKE%'` SET debug_sync='now SIGNAL t2_cont'; # Wait until T2 has entered its wait for T1 to commit, and T1 has # progressed into its commit phase. SET debug_sync='now WAIT_FOR t1_ready'; # Now kill the transaction T2. --replace_result $thd_id THD_ID eval KILL $thd_id; # Wait until T2 has reacted on the kill. SET debug_sync='now WAIT_FOR t2_killed'; # Now we can allow T1 to proceed. SET debug_sync='now SIGNAL t1_cont'; --let $slave_sql_errno= 1317,1927,1963 --source include/wait_for_slave_sql_error.inc STOP SLAVE IO_THREAD; SELECT * FROM t3 WHERE a >= 30 ORDER BY a; # Now we have to disable the debug_sync statements, so they do not trigger # when the events are retried. SET GLOBAL slave_parallel_threads=0; SET GLOBAL slave_parallel_threads=10; SET sql_log_bin=0; DROP FUNCTION foo; --delimiter || CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500)) RETURNS INT DETERMINISTIC BEGIN RETURN x; END || --delimiter ; SET sql_log_bin=1; --connection server_1 INSERT INTO t3 VALUES (39,0); --save_master_pos --connection server_2 --source include/start_slave.inc --sync_with_master SELECT * FROM t3 WHERE a >= 30 ORDER BY a; # Restore the foo() function. SET sql_log_bin=0; DROP FUNCTION foo; --delimiter || CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500)) RETURNS INT DETERMINISTIC BEGIN IF d1 != '' THEN SET debug_sync = d1; END IF; IF d2 != '' THEN SET debug_sync = d2; END IF; RETURN x; END || --delimiter ; SET sql_log_bin=1; --connection server_2 # Respawn all worker threads to clear any left-over debug_sync or other stuff. --source include/stop_slave.inc SET GLOBAL slave_parallel_threads=0; SET GLOBAL slave_parallel_threads=10; --source include/start_slave.inc --connection server_2 --source include/stop_slave.inc SET GLOBAL slave_parallel_threads=@old_parallel_threads; SET debug_sync = 'reset'; --source include/start_slave.inc --connection server_1 DROP function foo; DROP TABLE t3; SET debug_sync = 'reset'; --source include/rpl_end.inc