--source include/have_innodb.inc --source include/have_debug_sync.inc --source include/have_log_bin.inc # Test some group commit code paths by using debug_sync to do controlled # commits of 6 transactions: first 1 alone, then 3 as a group, then 2 as a # group. # # Group 3 is allowed to race as far as possible ahead before group 2 finishes # to check some edge case for concurrency control. CREATE TABLE t1 (a VARCHAR(10) PRIMARY KEY) ENGINE=innodb; # MDEV-515 takes X-lock on the table for the first insert. # So concurrent insert won't happen on the table INSERT INTO t1 VALUES(100); SELECT variable_value INTO @commits FROM information_schema.global_status WHERE variable_name = 'binlog_commits'; SELECT variable_value INTO @group_commits FROM information_schema.global_status WHERE variable_name = 'binlog_group_commits'; connect(con1,localhost,root,,); connect(con2,localhost,root,,); connect(con3,localhost,root,,); connect(con4,localhost,root,,); connect(con5,localhost,root,,); connect(con6,localhost,root,,); # Start group1 (with one thread) doing commit, waiting for # group2 to queue up before finishing. connection con1; SET DEBUG_SYNC= "commit_before_get_LOCK_after_binlog_sync SIGNAL group1_running WAIT_FOR group2_queued"; send INSERT INTO t1 VALUES ("con1"); # Make group2 (with three threads) queue up. # Make sure con2 is the group commit leader for group2. # Make group2 wait with running commit_ordered() until group3 has committed. connection con2; set DEBUG_SYNC= "now WAIT_FOR group1_running"; SET DEBUG_SYNC= "commit_after_prepare_ordered SIGNAL group2_con2"; SET DEBUG_SYNC= "commit_before_get_LOCK_after_binlog_sync SIGNAL group2_running"; SET DEBUG_SYNC= "commit_after_release_LOCK_log WAIT_FOR group3_committed"; SET DEBUG_SYNC= "commit_after_group_run_commit_ordered SIGNAL group2_visible WAIT_FOR group2_checked"; send INSERT INTO t1 VALUES ("con2"); connection con3; SET DEBUG_SYNC= "now WAIT_FOR group2_con2"; SET DEBUG_SYNC= "commit_after_prepare_ordered SIGNAL group2_con3"; send INSERT INTO t1 VALUES ("con3"); connection con4; SET DEBUG_SYNC= "now WAIT_FOR group2_con3"; SET DEBUG_SYNC= "commit_after_prepare_ordered SIGNAL group2_con4"; send INSERT INTO t1 VALUES ("con4"); # When group2 is queued, let group1 continue and queue group3. connection default; SET DEBUG_SYNC= "now WAIT_FOR group2_con4"; # At this point, trasaction 1 is still not visible as commit_ordered() has not # been called yet. SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; SELECT * FROM t1 ORDER BY a; SET DEBUG_SYNC= "now SIGNAL group2_queued"; connection con1; reap; # Now transaction 1 is visible. connection default; SELECT * FROM t1 ORDER BY a; connection con5; SET DEBUG_SYNC= "commit_before_get_LOCK_after_binlog_sync SIGNAL group3_con5"; SET DEBUG_SYNC= "commit_after_get_LOCK_log SIGNAL con5_leader WAIT_FOR con6_queued"; set DEBUG_SYNC= "now WAIT_FOR group2_running"; send INSERT INTO t1 VALUES ("con5"); connection con6; SET DEBUG_SYNC= "now WAIT_FOR con5_leader"; SET DEBUG_SYNC= "commit_after_prepare_ordered SIGNAL con6_queued"; send INSERT INTO t1 VALUES ("con6"); connection default; SET DEBUG_SYNC= "now WAIT_FOR group3_con5"; # Still only transaction 1 visible, as group2 have not yet run commit_ordered(). SELECT * FROM t1 ORDER BY a; SET DEBUG_SYNC= "now SIGNAL group3_committed"; SET DEBUG_SYNC= "now WAIT_FOR group2_visible"; # Now transactions 1-4 visible. SELECT * FROM t1 ORDER BY a; SET DEBUG_SYNC= "now SIGNAL group2_checked"; connection con2; reap; connection con3; reap; connection con4; reap; connection con5; reap; connection con6; reap; connection default; # Check all transactions finally visible. SELECT * FROM t1 ORDER BY a; SELECT variable_value - @commits FROM information_schema.global_status WHERE variable_name = 'binlog_commits'; SELECT variable_value - @group_commits FROM information_schema.global_status WHERE variable_name = 'binlog_group_commits'; SET DEBUG_SYNC= 'RESET'; DROP TABLE t1;