死鎖,其實是一個很有意思,也很有挑戰的技術問題,大概每個DBA和部分開發朋友都會在工作過程中遇見過。關于死鎖我會持續寫一個系列的案例分析,希望能夠對想了解死鎖的朋友有所幫助。
sess1
sess2
|
begin;
|
|
delete from t8 where b = 1;
|
begin;
|
|
insert into t8 values (NULL,1);
|
commit;
|
|
|
update t8 set
T2
|
begin;
|
begin;
|
|
insert into t7(id,a) values(26,10);
|
insert into t7(id,a) values(30,10);
|
|
|
insert into t7(id,a) values(40,9);
|
3.3 死鎖日志
-
------------------------
-
LATEST DETECTED DEADLOCK
-
------------------------
-
2017-09-17 15:15:03 7f78eac15700
-
*** (1) TRANSACTION:
-
TRANSACTION 462308661, ACTIVE 6 sec inserting
-
mysql tables in use 1, locked 1
-
LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s), undo log entries 1
-
MySQL thread id 3796966, OS thread handle 0x7f78ead9d700, query id 781045166 localhost root update
-
insert into t7(id,a) values(30,10)
-
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
-
RECORD LOCKS space id 231 page no 4 n bits 72 index `ua` of table `test`.`t7` trx id 462308661 lock mode S waiting
-
*** (2) TRANSACTION:
-
TRANSACTION 462308660, ACTIVE 43 sec inserting, thread declared inside InnoDB 5000
-
mysql tables in use 1, locked 1
-
4 lock struct(s), heap size 1184, 3 row lock(s), undo log entries 2
-
MySQL thread id 3796960, OS thread handle 0x7f78eac15700, query id 781045192 localhost root update
-
insert into t7(id,a) values(40,9)
-
*** (2) HOLDS THE LOCK(S):
-
RECORD LOCKS space id 231 page no 4 n bits 72 index `ua` of table `test`.`t7` trx id 462308660 lock_mode X locks rec but not gap
-
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
-
RECORD LOCKS space id 231 page no 4 n bits 72 index `ua` of table `test`.`t7` trx id 462308660 lock_mode X locks gap before rec insert intention waiting
-
*** WE ROLL BACK TRANSACTION (1)
日志分析
我們從時間線維度分析:
T2 insert into t7(id,a) values(26,10)語句insert 成功,持有a=10 的X 行鎖(X locks rec but not 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 ) 這是一個間隙鎖會申請鎖住[4,10],[10,20]之間的gap區域。從這里會發現,即使是RC事務隔離級別,也同樣會存在Next-Key Lock鎖,從而阻塞并發。
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
四 總結
首先感謝登博和姜承堯兩位德藝雙馨的MySQL技術大牛對死鎖技術知識的無私分享。本文案例和知識點一方面從官方文檔獲取,另一方面是根據兩位大牛的分享整理,算是站在巨人的肩膀上的學習總結。在研究分析死鎖案例的過程中,insert 的意向鎖 和 gap 鎖這種類型的鎖是比較難分析的,相信通過上面的分析總結大家能夠學習到 insert的鎖機制 ,如何加鎖,如何進行 insert 方面死鎖分析。
如果各位覺得閱讀本文能夠有所收獲 歡迎 打賞一瓶飲料