--source include/have_debug_sync.inc # Scenario: # C1 obtains implicit lock # C2 notices the implicit lock and decides to do impl-to-expl conversion # C1 starts commit and pauses after removing itself from rw-list, but before # (old code) changing state to TRX_STATE_COMMITED_IN_MEMORY # (new code) removing explicit locks # C3 ignores C1 (as it is no longer in rw-list) and adds own exclusive lock on # the record # C2 finishes impl-to-explicit conversion # (at this point we have two X locks on the same row) CREATE TABLE t1(id INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 (id) VALUES (1),(3); --connect(C1,localhost,root,,test) --connect(C2,localhost,root,,test) --connect(C3,localhost,root,,test) --connection C1 BEGIN; INSERT INTO t1 (id) VALUES (2); --connection C2 BEGIN; SET DEBUG_SYNC = "before_lock_rec_convert_impl_to_expl_for_trx SIGNAL c2_decided WAIT_FOR c2_can_convert"; SET DEBUG_SYNC = "lock_wait_will_wait SIGNAL c2_will_wait"; --send SELECT * FROM t1 WHERE id=2 FOR UPDATE --connection C1 SET DEBUG_SYNC = "now WAIT_FOR c2_decided"; SET DEBUG_SYNC = "before_lock_trx_release_locks SIGNAL c1_will_commit WAIT_FOR c1_can_commit"; --send COMMIT --connection C3 BEGIN; SET DEBUG_SYNC = "now WAIT_FOR c1_will_commit"; SELECT * FROM t1 WHERE id=2 FOR UPDATE; SET DEBUG_SYNC = "now SIGNAL c2_can_convert"; SET DEBUG_SYNC = "now WAIT_FOR c2_will_wait"; SET DEBUG_SYNC = "now SIGNAL c1_can_commit"; COMMIT; --connection C1 --reap --connection C2 --reap COMMIT; --connection default --disconnect C1 --disconnect C2 --disconnect C3 DROP TABLE t1; # Scenario: # C1 obtains implicit lock # C2 notices the implicit lock and decides to do impl-to-expl conversion # C1 XA Prepares # C1 starts commit and pauses after removing itself from rw-list, but before # (old code) changing state to TRX_STATE_COMMITED_IN_MEMORY # (new code) removing explicit locks # C3 ignores C1 (as it is no longer in rw-list) and adds own exclusive lock on # the record # C2 finishes impl-to-explicit conversion # (at this point we have two X locks on the same row) CREATE TABLE t1(id INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 (id) VALUES (1),(3); --connect(C1,localhost,root,,test) --connect(C2,localhost,root,,test) --connect(C3,localhost,root,,test) --connection C1 XA START "xid0"; INSERT INTO t1 (id) VALUES (2); --connection C2 BEGIN; SET DEBUG_SYNC = "before_lock_rec_convert_impl_to_expl_for_trx SIGNAL c2_decided WAIT_FOR c2_can_convert"; SET DEBUG_SYNC = "lock_wait_will_wait SIGNAL c2_will_wait"; --send SELECT * FROM t1 WHERE id=2 FOR UPDATE --connection C1 SET DEBUG_SYNC = "now WAIT_FOR c2_decided"; SET DEBUG_SYNC = "before_lock_trx_release_locks SIGNAL c1_will_commit WAIT_FOR c1_can_commit"; XA END "xid0"; XA PREPARE "xid0"; --send XA COMMIT "xid0" --connection C3 BEGIN; SET DEBUG_SYNC = "now WAIT_FOR c1_will_commit"; SELECT * FROM t1 WHERE id=2 FOR UPDATE; SET DEBUG_SYNC = "now SIGNAL c2_can_convert"; SET DEBUG_SYNC = "now WAIT_FOR c2_will_wait"; SET DEBUG_SYNC = "now SIGNAL c1_can_commit"; COMMIT; --connection C1 --reap --connection C2 --reap COMMIT; --connection default --disconnect C1 --disconnect C2 --disconnect C3 DROP TABLE t1; # Scenario: # C1 obtains implicit lock # C2 notices the implicit lock and decides to do impl-to-expl conversion # C1 starts commit and pauses after removing itself from rw-list, but before # (old code) changing state to TRX_STATE_COMMITED_IN_MEMORY # (new code) removing explicit locks # C3 ignores C1 (as it is no longer in rw-list) and decides to add its own # exclusive lock on the record # C2 finishes impl-to-explicit conversion # C3 proceeds to add its own lock # C1 finishes commit # C2 gets the lock granted and commits # C3 gets the lock granted and commits CREATE TABLE t1(id INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 (id) VALUES (1),(3); --connect(C1,localhost,root,,test) --connect(C2,localhost,root,,test) --connect(C3,localhost,root,,test) --connection C1 BEGIN; INSERT INTO t1 (id) VALUES (2); --connection C2 BEGIN; SET DEBUG_SYNC = "before_lock_rec_convert_impl_to_expl_for_trx SIGNAL c2_decided WAIT_FOR c2_can_convert"; SET DEBUG_SYNC = "after_lock_rec_convert_impl_to_expl_for_trx SIGNAL c2_done_conversion"; --send SELECT * FROM t1 WHERE id=2 FOR UPDATE --connection C1 SET DEBUG_SYNC = "now WAIT_FOR c2_decided"; SET DEBUG_SYNC = "before_lock_trx_release_locks SIGNAL c1_will_commit WAIT_FOR c1_can_commit"; --send COMMIT --connection C3 BEGIN; SET DEBUG_SYNC = "now WAIT_FOR c1_will_commit"; SET DEBUG_SYNC = "lock_wait_will_wait SIGNAL c3_will_wait"; SET DEBUG_SYNC = "after_lock_clust_rec_read_check_and_lock_impl_to_expl SIGNAL c3_will_lock WAIT_FOR c3_can_lock"; --send SELECT * FROM t1 WHERE id=2 FOR UPDATE --connection default SET DEBUG_SYNC = "now WAIT_FOR c3_will_lock"; SET DEBUG_SYNC = "now SIGNAL c2_can_convert"; SET DEBUG_SYNC = "now WAIT_FOR c2_done_conversion"; SET DEBUG_SYNC = "now SIGNAL c3_can_lock"; SET DEBUG_SYNC = "now WAIT_FOR c3_will_wait"; SET DEBUG_SYNC = "now SIGNAL c1_can_commit"; COMMIT; --connection C1 --reap --connection C2 --reap COMMIT; --connection C3 --reap COMMIT; --connection default --disconnect C1 --disconnect C2 --disconnect C3 DROP TABLE t1; # Scenario: # C1 obtains implicit lock # C2 notices the implicit lock and decides to do impl-to-expl conversion # C1 PREPARES # C1 starts commit and pauses after removing itself from rw-list, but before # (old code) changing state to TRX_STATE_COMMITED_IN_MEMORY # (new code) removing explicit locks # C3 ignores C1 (as it is no longer in rw-list) and decides to adds own exclusive lock on the record # C2 finishes impl-to-explicit conversion # C3 proceeds to add its own lock # C1 finishes commit # C2 gets the lock granted and commits # C3 gets the lock granted and commits CREATE TABLE t1(id INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 (id) VALUES (1),(3); --connect(C1,localhost,root,,test) --connect(C2,localhost,root,,test) --connect(C3,localhost,root,,test) --connection C1 XA START "xid0"; INSERT INTO t1 (id) VALUES (2); --connection C2 BEGIN; SET DEBUG_SYNC = "before_lock_rec_convert_impl_to_expl_for_trx SIGNAL c2_decided WAIT_FOR c2_can_convert"; SET DEBUG_SYNC = "after_lock_rec_convert_impl_to_expl_for_trx SIGNAL c2_done_conversion"; --send SELECT * FROM t1 WHERE id=2 FOR UPDATE --connection C1 SET DEBUG_SYNC = "now WAIT_FOR c2_decided"; SET DEBUG_SYNC = "before_lock_trx_release_locks SIGNAL c1_will_commit WAIT_FOR c1_can_commit"; XA END "xid0"; XA PREPARE "xid0"; --send XA COMMIT "xid0" --connection C3 BEGIN; SET DEBUG_SYNC = "now WAIT_FOR c1_will_commit"; SET DEBUG_SYNC = "lock_wait_will_wait SIGNAL c3_will_wait"; SET DEBUG_SYNC = "after_lock_clust_rec_read_check_and_lock_impl_to_expl SIGNAL c3_will_lock WAIT_FOR c3_can_lock"; --send SELECT * FROM t1 WHERE id=2 FOR UPDATE --connection default SET DEBUG_SYNC = "now WAIT_FOR c3_will_lock"; SET DEBUG_SYNC = "now SIGNAL c2_can_convert"; SET DEBUG_SYNC = "now WAIT_FOR c2_done_conversion"; SET DEBUG_SYNC = "now SIGNAL c3_can_lock"; SET DEBUG_SYNC = "now WAIT_FOR c3_will_wait"; SET DEBUG_SYNC = "now SIGNAL c1_can_commit"; COMMIT; --connection C1 --reap --connection C2 --reap COMMIT; --connection C3 --reap COMMIT; --connection default --disconnect C1 --disconnect C2 --disconnect C3 DROP TABLE t1; # Scenario: # C1 obtains implicit lock # C2 notices the implicit lock and decides to do validation # C1 starts commit and pauses after removing itself from rw-list, but before # (old code) changing state to TRX_STATE_COMMITED_IN_MEMORY # (new code) removing explicit locks # C3 ignores C1 (as it is no longer in rw-list) and adds own exclusive lock on # the record # C2 performs validation CREATE TABLE t1(id INT PRIMARY KEY,val INT, KEY val(val)) ENGINE=InnoDB; INSERT INTO t1 (id,val) VALUES (1,1),(3,3); --connect(C1,localhost,root,,test) --connect(C2,localhost,root,,test) --connect(C3,localhost,root,,test) --connection C1 BEGIN; INSERT INTO t1 (id,val) VALUES (2,2); --connection C2 BEGIN; SET DEBUG_SYNC = "lock_rec_convert_impl_to_expl_will_validate SIGNAL c2_decided WAIT_FOR c2_can_validate"; SET DEBUG_SYNC = "lock_wait_will_wait SIGNAL c2_will_wait"; --send SELECT * FROM t1 WHERE val=2 FOR UPDATE --connection C1 SET DEBUG_SYNC = "now WAIT_FOR c2_decided"; SET DEBUG_SYNC = "before_lock_trx_release_locks SIGNAL c1_will_commit WAIT_FOR c1_can_commit"; --send COMMIT --connection C3 BEGIN; SET DEBUG_SYNC = "now WAIT_FOR c1_will_commit"; SELECT * FROM t1 WHERE val=2 FOR UPDATE; SET DEBUG_SYNC = "now SIGNAL c2_can_validate"; SET DEBUG_SYNC = "now WAIT_FOR c2_will_wait"; SET DEBUG_SYNC = "now SIGNAL c1_can_commit"; COMMIT; --connection C1 --reap --connection C2 --reap COMMIT; --connection default --disconnect C1 --disconnect C2 --disconnect C3 DROP TABLE t1;