死鎖案例二
1、環境說明
MySQL5.6.33,隔離級別是RR。表結構及資料:
Create table t1(id int not null primary key auto_increment,c1 int,c2 int,c3 int, unique key(c1),unique key(c2));
insert into t1(c1,c2,c3) values(1,3,4),(6,6,10),(9,9,14);
2、測試用例
session1 | session2 | session3 |
begin; | begin; | begin; |
insert into t1 (c1,c2,c3) values(4,4,1); |
||
insert into t1 (c1,c2,c3) values(4,4,2); |
||
insert into t1 (c1,c2,c3) values(4,4,3); |
||
commit; | ||
Update t1 set c3=5 where c1=4; |
||
Update t1 set c3=5 where c1=4; |
||
deadlock; |
3、死鎖日誌
4、分析死鎖日誌
從死鎖日誌上可以看到:
TRANSACTION 7973:
Update t1 set c3=5 where c1=4語句在等待二級索引c1上(4,6)上的X型別的記錄鎖(lock_mode X locks rec but not gap)
TRANSACTION 7974:
擁有二級索引c1上(4,6)上S型別的next key鎖(lock mode S),等待申請(4,6)上的記錄鎖(lock_mode X locks rec but not gap)
但從死鎖日誌上只看到兩個update語句互相等待,不知道業務邏輯場景的話,很難找到原因。
注:這裡留下疑問,為什麼主鍵是6呢,不是4?這個和自增鍵有關,關於自增值這裡不做過多考慮,感興趣的自行測試分析。
5、加鎖原理
1)關於insert唯一鍵加鎖時重複鍵判斷加S型別next-key鎖的加鎖原理見之前部落格:
https://blog.csdn.net/yanzongshuai/article/details/79326637
以及https://blog.csdn.net/yanzongshuai/article/details/79301868
注意,這裡發生重複鍵加S 型別next key鎖時,不論是什麼隔離級別,都會加這樣的鎖。
2)關於隱式鎖轉換顯式鎖流程見之前部落格:
https://blog.csdn.net/yanzongshuai/article/details/79306514
https://blog.csdn.net/yanzongshuai/article/details/79254031
https://blog.csdn.net/yanzongshuai/article/details/79252679
3)關於update加鎖原理見之前部落格:
https://blog.csdn.net/yanzongshuai/article/details/80870949
https://blog.csdn.net/yanzongshuai/article/details/80870957
https://blog.csdn.net/yanzongshuai/article/details/80872095
6、解析
1)session1執行insert into t1 (c1,c2,c3) values(4,4,1);實際上是沒有加任何鎖的。
2)session2執行insert into t1 (c1,c2,c3) values(4,4,2);二級索引(4)和session1的發生衝突,使session1的隱式鎖轉換成顯式鎖;發生唯一衝突,則對(4)加S型別的next key鎖,此時session1已經加了X鎖,發生等待;
3)session3執行insert into t1 (c1,c2,c3) values(4,4,3);同理,等待session1釋放二級索引c1(4)上的X鎖,申請S型別的next key鎖。
4)session1執行commit後,session2和session3報錯:ERROR 1062 (23000): Duplicate entry '4' for key 'c1',同時會申請到S型別的next key鎖。
5)session2執行Update t1 set c3=5 where c1=4;從之前部落格
https://blog.csdn.net/yanzongshuai/article/details/80872095
可知在search階段會對二級索引記錄(4)申請X型別的記錄鎖。session3已擁有S型別next key鎖,所以發生等待;
6)session3再執行Update t1 set c3=5 where c1=4;同理,會申請X型別的記錄鎖,等待session2釋放其S型別next key鎖。此時發生死鎖。
7、解決方法
楊奇龍老師解釋可以使用使用insert on duplicate key語句來代替原來的insert語句。這2個語句的加鎖不一樣,感興趣的可以研究下。
8、參考
https://mp.weixin.qq.com/s/96CDhpgu5uUQ7qKYhKgt3w
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31493717/viewspace-2157519/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL死鎖案例二(自增列導致死鎖)MySql
- 死鎖案例分析
- 死鎖案例三
- GreatSQL 死鎖案例分析SQL
- 【MySQL】死鎖案例之六MySql
- 【MySQL】死鎖案例之七MySql
- 【MySQL】死鎖案例之八MySql
- 故障分析 | MySQL死鎖案例分析MySql
- MySQL:Innodb 一個死鎖案例MySql
- MySQL批量更新死鎖案例分析MySql
- MySQL死鎖案例一(回滾導致死鎖)MySql
- 剖析6個MySQL死鎖案例的原因以及死鎖預防策略MySql
- MySQL死鎖案例分析一(先delete,再insert,導致死鎖)MySqldelete
- MySQL死鎖案例 – Learn. Write. Repeat.MySql
- 死鎖
- 什麼是死鎖?如何解決死鎖?
- 面試官:什麼是死鎖?怎麼排查死鎖?怎麼避免死鎖?面試
- 死鎖概述
- 作業系統(5) 死鎖的概念 死鎖產生的必要條件 死鎖的處理策略 預防死鎖 避免死鎖 死鎖的檢測和解除 銀行家演算法作業系統演算法
- 例項詳解 Java 死鎖與破解死鎖Java
- 檢視oracle死鎖程式並結束死鎖Oracle
- MySQL 死鎖和鎖等待MySql
- 死鎖和可重入鎖
- 面試:什麼是死鎖,如何避免或解決死鎖;MySQL中的死鎖現象,MySQL死鎖如何解決面試MySql
- SQL SERVER死鎖查詢,死鎖分析,解鎖,查詢佔用SQLServer
- 死鎖是什麼?如何預防和避免死鎖?
- MySQL死鎖系列-線上死鎖問題排查思路MySql
- 死鎖-舉例
- 併發:死鎖
- 遭遇ITL死鎖
- GCD 死鎖原因GC
- MySQL:一個死鎖分析 (未分析出來的死鎖)MySql
- Mysql 兩階段鎖和死鎖MySql
- 鎖的使用與死鎖的避免
- SQLServer的死鎖分析(1):頁鎖SQLServer
- mysql行鎖和死鎖檢測MySql
- 如何避免死鎖和活鎖? - simar
- SQL Server 的死鎖SQLServer