mysql insert導致死鎖

水逸冰發表於2020-05-17

兩個insert語句發生死鎖的案例。

一. 準備資料

CREATE TABLE `t1` (
`a` int(11) NOT NULL,
PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
insert into t1 values(1);
mysql> insert into t1 values(1);
Query OK, 1 row affected (0.20 sec)
mysql> select * from t1;
+---+
| a |
+---+
| 1 |
+---+
1 row in set (0.00 sec)


二. 發起如下事務


會話1

會話2

會話3

begin;

delete from t1 where a=1;




begin;

insert into t1 select 1;




begin;

insert into t1 select 1;

Commit





ERROR 1213 (40001): Deadlock found when   trying to get lock; try restarting transaction

簡單理解下,刪除資料的會話持有X鎖,導致兩條insert語句需要等待,這沒問題,

但是為什麼刪除提交後,兩個競爭關係出現了死鎖。

show engine innodb status部分結果:

------------------------
LATEST DETECTED DEADLOCK
------------------------
2020-05-17 13:50:24 0x7f660c3f0700
*** (1) TRANSACTION:
TRANSACTION 4377, ACTIVE 13 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s)
MySQL thread id 3, OS thread handle 140076399294208, query id 59 localhost root executing
insert into t1 select 1
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 99 page no 3 n bits 72 index PRIMARY of table `ming`.`t1` trx id 4377 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 32
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 000000001114; asc       ;;
 2: len 7; hex 3400000144129f; asc 4   D  ;;
*** (2) TRANSACTION:
TRANSACTION 4378, ACTIVE 10 sec inserting, thread declared inside InnoDB 1
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1136, 2 row lock(s)
MySQL thread id 4, OS thread handle 140076268848896, query id 61 localhost root executing
insert into t1 select 1
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 99 page no 3 n bits 72 index PRIMARY of table `ming`.`t1` trx id 4378 lock mode S
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 32
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 000000001114; asc       ;;
 2: len 7; hex 3400000144129f; asc 4   D  ;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 99 page no 3 n bits 72 index PRIMARY of table `ming`.`t1` trx id 4378 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 32
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 000000001114; asc       ;;
 2: len 7; hex 3400000144129f; asc 4   D  ;;
*** WE ROLL BACK TRANSACTION (2)

可以看到會話2正在等待一個X行鎖,會話3也在等待X行鎖,但是同時持有一個S鎖。

這個S鎖是怎麼來的呢?

當進行唯一性衝突檢測時,需要先加一個 S 鎖。

那麼整個過程就是如下所示

會話1

會話2

會話3

begin;

delete from t1 where a=1;

持有a=1就的X行鎖




begin;

insert into t1 select 1;

為了判斷唯一性,請求a=1的next-key   lock S鎖被阻塞,等待




begin;

insert into t1 select 1;

為了判斷唯一性,請求a=1的next-key   lock S鎖被阻塞,等待

Commit

釋放a=1上的鎖




拿到a=1的next-key lock   S鎖,繼續嘗試拿a=1的X 行鎖,但是被會話3的S鎖阻塞

拿到a=1的next-key lock   S鎖,繼續嘗試拿a=1的X 行鎖,嘗試拿到a=1的X 行鎖,但是被會話2的S鎖阻塞。

觸發死鎖

ERROR 1213 (40001): Deadlock found when   trying to get lock; try restarting transaction

 



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31480688/viewspace-2692592/,如需轉載,請註明出處,否則將追究法律責任。

相關文章