mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Merge 10.6 into 10.7
This commit is contained in:
@@ -16,19 +16,19 @@ SET DEBUG_SYNC = 'innodb_row_search_for_mysql_exit SIGNAL first_del_row_search_m
|
||||
--connect(con_ins_1,localhost,root,,)
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR first_del_row_search_mvcc_finished';
|
||||
# It's supposed the following INSERT will be suspended just after
|
||||
# lock_wait_suspend_thread_enter syncpoint, and will be awaken
|
||||
# lock_wait_start syncpoint, and will be awaken
|
||||
# after the previous DELETE commits. ib_after_row_insert will be executed
|
||||
# after the INSERT is woken up. The previous DELETE will wait for
|
||||
# first_del_cont signal before commit, and this signal will be sent later.
|
||||
# So it's safe to use two signals in a row here, it's guaranted the first
|
||||
# signal will be received before the second signal is sent.
|
||||
SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL first_ins_locked';
|
||||
SET DEBUG_SYNC = 'lock_wait_start SIGNAL first_ins_locked';
|
||||
SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL first_ins_row_inserted WAIT_FOR first_ins_cont';
|
||||
--send INSERT INTO t VALUES(10, 20)
|
||||
|
||||
--connect(con_del_2,localhost,root,,)
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR first_ins_locked';
|
||||
SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL second_del_locked';
|
||||
SET DEBUG_SYNC = 'lock_wait_start SIGNAL second_del_locked';
|
||||
###############################################################################
|
||||
# This DELETE is locked by the previous DELETE, after that DELETE is
|
||||
# committed, it will still be locked by the next INSERT on delete-marked
|
||||
|
102
mysql-test/suite/innodb/t/deadlock_victim_race.test
Normal file
102
mysql-test/suite/innodb/t/deadlock_victim_race.test
Normal file
@@ -0,0 +1,102 @@
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_debug_sync.inc
|
||||
--source include/count_sessions.inc
|
||||
|
||||
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; # trx 1
|
||||
SELECT * FROM t WHERE a = 20 FOR UPDATE;
|
||||
# Locking order:
|
||||
# (10,10) (20,20) (30,30)
|
||||
# ^
|
||||
# trx 1
|
||||
|
||||
--connect(con_2,localhost,root,,)
|
||||
# RC is neccessary to do semi-consistent read
|
||||
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
BEGIN; # trx 2
|
||||
# The first time it will be hit on trying to lock (20,20), the second hit
|
||||
# will be on (30,30).
|
||||
SET DEBUG_SYNC = 'lock_trx_handle_wait_enter SIGNAL upd_locked WAIT_FOR upd_cont EXECUTE 2';
|
||||
# We must not modify primary key fields to cause rr_sequential() read record
|
||||
# function choosing in mysql_update(), i.e. both query_plan.using_filesort and
|
||||
# query_plan.using_io_buffer must be false during init_read_record() call.
|
||||
--send UPDATE t SET b = 100
|
||||
|
||||
--connect(con_3,localhost,root,,)
|
||||
BEGIN; # trx 3
|
||||
# The following update is necessary to increase the transaction weight, which is
|
||||
# calculated as the number of locks + the number of undo records during deadlock
|
||||
# report. Victim's transaction should have minimum weight. We need trx 2 to be
|
||||
# choosen as victim, that's why we need to increase the current transaction
|
||||
# weight.
|
||||
UPDATE t2 SET a = a + 100;
|
||||
SELECT * FROM t WHERE a = 30 FOR UPDATE;
|
||||
SET DEBUG_SYNC='now WAIT_FOR upd_locked';
|
||||
# Locking queue:
|
||||
# (10,10) (20,20) (30,30)
|
||||
# ^ ^ ^
|
||||
# trx 2 trx 1 trx 3
|
||||
# trx 2 (waiting for 1)
|
||||
|
||||
SET DEBUG_SYNC = 'lock_wait_start SIGNAL sel_locked';
|
||||
--send SELECT * FROM t WHERE a = 20 FOR UPDATE
|
||||
--connection default
|
||||
SET DEBUG_SYNC='now WAIT_FOR sel_locked';
|
||||
# Locking queue:
|
||||
# (10,10) (20,20) (30,30)
|
||||
# ^ ^ ^
|
||||
# trx 2 trx 1 trx 3
|
||||
# trx 2 (waiting for 1)
|
||||
# trx 3 (waiting for 1)
|
||||
#
|
||||
# Note trx 1 must grant lock to trx2 before trx 2 checks the lock state in
|
||||
# lock_trx_handle_wait(), i.e. the function must return DB_SUCCESS, that's why
|
||||
# the following ROLLBACK must be executed before sending upd_cont signal.
|
||||
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)
|
||||
# ^ ^ ^
|
||||
# trx 2 trx 2 trx 3
|
||||
# trx 3 (waiting for 2) trx 2 (waiting for 3)
|
||||
#
|
||||
# Deadlock happened after trx 1 granted lock to trx 2, and trx2 continued
|
||||
# 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";
|
||||
--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;
|
||||
|
||||
--connection con_3
|
||||
--reap
|
||||
|
||||
--connection con_2
|
||||
# As lock_trx_handle_wait() wrongly returned DB_SUCCESS instead of
|
||||
# DB_DEADLOCK, row_search_mvcc() of trx 2 behaves so as if (30,30) was locked.
|
||||
# But the waiting(for trx 3) lock was cancelled by deadlock checker after
|
||||
# trx 2 was choosen as a victim (see lock_cancel_waiting_and_release() call
|
||||
# from Deadlock::report() for details). The try to update non-locked record
|
||||
# will cause assertion if the bug is not fixed.
|
||||
--error ER_LOCK_DEADLOCK
|
||||
--reap
|
||||
|
||||
--disconnect con_3
|
||||
--disconnect con_2
|
||||
|
||||
--connection default
|
||||
SET DEBUG_SYNC = 'RESET';
|
||||
DROP TABLE t;
|
||||
DROP TABLE t2;
|
||||
|
||||
--source include/wait_until_count_sessions.inc
|
@@ -38,8 +38,40 @@ eval CREATE TABLE `$d255`.`_$d250`
|
||||
--replace_result $d255 d255
|
||||
eval CREATE TABLE `$d255`.`$d250`
|
||||
(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-29258 Failing assertion for name length on RENAME TABLE
|
||||
--echo #
|
||||
|
||||
let $d245=-------------------------------------------------;
|
||||
--replace_result $d245 d245 $d255 d255
|
||||
eval CREATE TABLE `$d255`.`$d245` (x INT) ENGINE=InnoDB;
|
||||
--replace_result $d250 d250 $d255 d255
|
||||
eval DROP TABLE `$d255`.`$d250`;
|
||||
|
||||
--replace_result $d245 d245 $d250 d250 d255 d255
|
||||
eval RENAME TABLE `$d255`.`$d245` TO `$d255`.`$d250`;
|
||||
--replace_result $d250 d250 $d255 d255
|
||||
eval RENAME TABLE `$d255`.`$d250` TO a;
|
||||
--replace_result $d255 d255
|
||||
DROP TABLE a,t;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-29409 Buffer overflow in my_wc_mb_filename() on RENAME TABLE
|
||||
--echo #
|
||||
|
||||
let $d225=#############################################;
|
||||
let $d320=################################################################;
|
||||
|
||||
--replace_result $d255 d255
|
||||
eval CREATE TABLE `$d255`.t(a INT PRIMARY KEY)ENGINE=InnoDB;
|
||||
--replace_result $d255 d255 $d320 d320
|
||||
eval CREATE TABLE `$d255`.u(a INT PRIMARY KEY,
|
||||
CONSTRAINT `$d320` FOREIGN KEY (a) REFERENCES `$d255`.t (a)) ENGINE=InnoDB;
|
||||
--replace_result $d255 d255
|
||||
eval RENAME TABLE `$d255`.u TO u;
|
||||
DROP TABLE u;
|
||||
--replace_result $d255 d255
|
||||
eval DROP DATABASE `$d255`;
|
||||
DROP TABLE t;
|
||||
|
||||
--echo # End of 10.3 tests
|
||||
|
@@ -28,7 +28,7 @@ start transaction;
|
||||
select f1, f2 from t2 for update;
|
||||
|
||||
connection default;
|
||||
set debug_sync='lock_wait_suspend_thread_enter SIGNAL upd_waiting WAIT_FOR go_upd';
|
||||
set debug_sync='lock_wait_start SIGNAL upd_waiting WAIT_FOR go_upd';
|
||||
send update t1 set f1 = 10 where f1 = 2;
|
||||
|
||||
connection con1;
|
||||
@@ -72,7 +72,7 @@ start transaction;
|
||||
select f1, f2 from t2 for update;
|
||||
|
||||
connection default;
|
||||
set debug_sync='lock_wait_suspend_thread_enter SIGNAL upd_waiting WAIT_FOR go_upd';
|
||||
set debug_sync='lock_wait_start SIGNAL upd_waiting WAIT_FOR go_upd';
|
||||
send update t1 set f2 = 28 where f2 = 91;
|
||||
|
||||
connection con1;
|
||||
@@ -120,7 +120,7 @@ start transaction;
|
||||
select f1 from t3 for update;
|
||||
|
||||
connection default;
|
||||
set debug_sync='lock_wait_suspend_thread_enter SIGNAL upd_waiting WAIT_FOR go_upd';
|
||||
set debug_sync='lock_wait_start SIGNAL upd_waiting WAIT_FOR go_upd';
|
||||
send update t1 set f1 = 10 where f1 = 2;
|
||||
|
||||
connection con1;
|
||||
@@ -183,7 +183,7 @@ start transaction;
|
||||
select f1 from t3 for update;
|
||||
|
||||
connection default;
|
||||
set debug_sync='lock_wait_suspend_thread_enter SIGNAL upd_waiting WAIT_FOR go_upd';
|
||||
set debug_sync='lock_wait_start SIGNAL upd_waiting WAIT_FOR go_upd';
|
||||
send update t1 set f2 = 28 where f2 = 91;
|
||||
|
||||
connection con1;
|
||||
|
Reference in New Issue
Block a user