LOCK WAIT 表示正在等待鎖,2 lock struct(s) 表示 trx->trx_locks 鎖鏈表的長度為2,每個鏈表節點代表該事務持有的一個鎖結構,包括表鎖,記錄鎖以及自增鎖等。本用例中 2locks 表示 IX 鎖和lock_mode X (Next-key lock)
1 row lock(s) 表示當前事務持有的行記錄鎖/ gap 鎖的個數。
MySQL thread id 37, OS thread handle 140445500716800, query id 1234 127.0.0.1 root updating
MySQL thread id 37 表示執行該事務的線程 ID 為 37 (即 show processlist; 展示的 ID )
delete from student where stuno=5 表示事務1正在執行的 sql,比較難受的事情是 show engine innodb status 是查看不到完整的 sql 的,通常顯示當前正在等待鎖的 sql。
***** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 11 page no 5 n bits 72 index idx_stuno of table cw****.****student trx id 2322 lock_mode X waiting
RECORD LOCKS 表示記錄鎖, 此條內容表示事務 1 正在等待表 student 上的 idx_stuno 的 X 鎖,本案例中其實是 Next-Key Lock 。
事務2的 log 和上面分析類似:
2.***** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 11 page no 5 n bits 72 index idx_stuno of table cw****.****student trx id 2321 lock_mode X
顯示事務 2 的 insert into student(stuno,score) values(2,10) 持有了 a=5 的 Lock mode X
LOCK_gap,不過我們從日志里面看不到事務2執行的 delete from student where stuno=5;
這點也是造成 DBA 僅僅根據日志難以分析死鎖的問題的根本原因。
3.***** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 11 page no 5 n bits 72 index idx_stuno of table cw****.****student trx id 2321 lock_mode X locks gap before rec insert intention waiting
表示事務 2 的 insert 語句正在等待插入意向鎖 lock_mode X locks gap before rec insert intention waiting ( LOCK_X + LOCK_REC_gap )
4、經典案例分析
4.1、事務并發 insert 唯一鍵沖突
日志分析如下:
事務 T2 insert into t7(id,a) values (26,10) 語句 insert 成功,持有 a=10 的 排他行鎖( Xlocks rec but no gap )
事務 T1 insert into t7(id,a) values (30,10), 因為T2的第一條 insert 已經插入 a=10 的記錄,事務 T1 insert a=10 則發生唯一鍵沖突,需要申請對沖突的唯一索引加上S Next-key Lock( 即 lock mode S waiting ) 這是一個間隙鎖會申請鎖住(,10],(10,20]之間的 gap 區域。
事務 T2 insert into t7(id,a) values (40,9)該語句插入的 a=9 的值在事務 T1 申請的 gap 鎖4-10之間, 故需事務 T2 的第二條 insert 語句要等待事務 T1 的 S-Next-key Lock 鎖釋放,在日志中顯示 lock_mode X locks gap before rec insert intention waiting 。
4.2、先 update 再 insert 的并發死鎖問題
可以看到兩個事務 update 不存在的記錄,先后獲得間隙鎖( gap 鎖),gap 鎖之間是兼容的所以在update環節不會阻塞。兩者都持有 gap 鎖,然后去競爭插入意向鎖。當存在其他會話持有 gap 鎖的時候,當前會話申請不了插入意向鎖,導致死鎖。