mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-29515 innodb.deadlock_victim_race is unstable
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.
This commit is contained in:
@@ -2,6 +2,17 @@
|
||||
--source include/have_debug_sync.inc
|
||||
--source include/count_sessions.inc
|
||||
|
||||
--connect(cancel_purge,localhost,root,,)
|
||||
# Purge can cause deadlock in the test, requesting page's RW_X_LATCH for trx
|
||||
# ids reseting, after trx 2 acqured RW_S_LATCH and suspended in debug sync point
|
||||
# lock_trx_handle_wait_enter, waiting for upd_cont signal, which must be
|
||||
# emitted after the last SELECT in this test. The last SELECT will hang waiting
|
||||
# for purge RW_X_LATCH releasing, and trx 2 will be rolled back by timeout.
|
||||
# The last SELECT will then be successfully executed instead of finishing by
|
||||
# lock wait timeout.
|
||||
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;
|
||||
|
||||
@@ -60,7 +71,6 @@ SET DEBUG_SYNC='now WAIT_FOR sel_locked';
|
||||
ROLLBACK;
|
||||
SET DEBUG_SYNC='now SIGNAL upd_cont';
|
||||
|
||||
SET innodb_lock_wait_timeout=1;
|
||||
SET DEBUG_SYNC="now WAIT_FOR upd_locked";
|
||||
# Locking queue:
|
||||
# (10,10) (20,20) (30,30)
|
||||
@@ -72,11 +82,12 @@ SET DEBUG_SYNC="now WAIT_FOR upd_locked";
|
||||
# sequential read (with rr_sequential() read record function), and requested
|
||||
# lock on (30,30). But the deadlock has not been determined yet.
|
||||
|
||||
SET DEBUG_SYNC="lock_wait_end SIGNAL upd_cont";
|
||||
SET SESSION innodb_lock_wait_timeout=1;
|
||||
--error ER_LOCK_WAIT_TIMEOUT
|
||||
# The deadlock will be determined in lock_wait() after lock wait timeout
|
||||
# expired.
|
||||
SELECT * FROM t WHERE a = 10 FOR UPDATE;
|
||||
SET DEBUG_SYNC="now SIGNAL upd_cont";
|
||||
|
||||
--connection con_3
|
||||
--reap
|
||||
@@ -98,5 +109,5 @@ SELECT * FROM t WHERE a = 10 FOR UPDATE;
|
||||
SET DEBUG_SYNC = 'RESET';
|
||||
DROP TABLE t;
|
||||
DROP TABLE t2;
|
||||
|
||||
--disconnect cancel_purge
|
||||
--source include/wait_until_count_sessions.inc
|
||||
|
Reference in New Issue
Block a user