mirror of
https://github.com/MariaDB/server.git
synced 2025-01-30 18:41:56 +01:00
5ab78cf340
The test is unstable because 'UPDATE t SET b = 100' latches a page and waits for 'upd_cont' signal in lock_trx_handle_wait_enter sync point, then purge requests RW_X_LATCH on the same page, and then 'SELECT * FROM t WHERE a = 10 FOR UPDATE' requests RW_S_LATCH, waiting for RW_X_LATCH requested by purge. 'UPDATE t SET b = 100' can't release page latch as it waits for upd_cont signal, which must be emitted after 'SELECT * FROM t WHERE a = 10 FOR UPDATE' acquired RW_S_LATCH. So we have a deadlock, which is resolved by finishing the debug sync point wait by timeout, and the 'UPDATE t SET b = 100' releases it's record locks rolling back the transaction, and 'SELECT * FROM t WHERE a = 10 FOR UPDATE' is finished successfully instead of finishing by lock wait timeout. The fix is to forbid purging during the test by opening read view in a separate connection before the first insert into the table. Besides, 'lock_wait_end' syncpoint is not needed, as it enough to wait the end of the SELECT execution to let the UPDATE to continue.
46 lines
1.4 KiB
Text
46 lines
1.4 KiB
Text
connect cancel_purge,localhost,root,,;
|
|
START TRANSACTION WITH CONSISTENT SNAPSHOT;
|
|
connection default;
|
|
CREATE TABLE t (a int PRIMARY KEY, b int) engine = InnoDB;
|
|
CREATE TABLE t2 (a int PRIMARY KEY) engine = InnoDB;
|
|
INSERT INTO t VALUES (10, 10), (20, 20), (30, 30);
|
|
INSERT INTO t2 VALUES (10), (20), (30);
|
|
BEGIN;
|
|
SELECT * FROM t WHERE a = 20 FOR UPDATE;
|
|
a b
|
|
20 20
|
|
connect con_2,localhost,root,,;
|
|
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
|
BEGIN;
|
|
SET DEBUG_SYNC = 'lock_trx_handle_wait_enter SIGNAL upd_locked WAIT_FOR upd_cont EXECUTE 2';
|
|
UPDATE t SET b = 100;
|
|
connect con_3,localhost,root,,;
|
|
BEGIN;
|
|
UPDATE t2 SET a = a + 100;
|
|
SELECT * FROM t WHERE a = 30 FOR UPDATE;
|
|
a b
|
|
30 30
|
|
SET DEBUG_SYNC='now WAIT_FOR upd_locked';
|
|
SET DEBUG_SYNC = 'lock_wait_start SIGNAL sel_locked';
|
|
SELECT * FROM t WHERE a = 20 FOR UPDATE;
|
|
connection default;
|
|
SET DEBUG_SYNC='now WAIT_FOR sel_locked';
|
|
ROLLBACK;
|
|
SET DEBUG_SYNC='now SIGNAL upd_cont';
|
|
SET DEBUG_SYNC="now WAIT_FOR upd_locked";
|
|
SET SESSION innodb_lock_wait_timeout=1;
|
|
SELECT * FROM t WHERE a = 10 FOR UPDATE;
|
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
|
SET DEBUG_SYNC="now SIGNAL upd_cont";
|
|
connection con_3;
|
|
a b
|
|
20 20
|
|
connection con_2;
|
|
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
|
disconnect con_3;
|
|
disconnect con_2;
|
|
connection default;
|
|
SET DEBUG_SYNC = 'RESET';
|
|
DROP TABLE t;
|
|
DROP TABLE t2;
|
|
disconnect cancel_purge;
|