一個MySQL死鎖問題的反思
很早之前我寫過幾篇關於MySQL死鎖的分析,比如
但是感覺不過癮,而且分析的都是一些特定的場景,好像還缺少一些舉一反三的感覺,所以今天就補上這一波。
MySQL裡的鎖相容列表大體是這樣的關係,如果第一次看會有些暈,感覺抓不住重點,其實有一點小技巧。
首先InnoDB實現了兩種類似的行鎖,即S(共享鎖)和X(排他鎖),而InnoDB層面的表級意向鎖有IS(意向共享鎖)和IX9意向排他鎖),意向鎖之間是互相相容的,這句話很重要,按照這個思路里面一半的內容就明確了。而另外一部分則是S和X的相容性。帶著S鎖和X鎖的組合都是互相排斥,只有一類場景例外,那就是都是S鎖,是相容的。所以這個圖按照這個思路幾乎不用記就能基本理解了。
看起來S鎖的組合是很柔和的,從這種場景來看保持相容,那麼出死鎖的概率應該很低吧,其實在RR,RC隔離級別下我們可以逐步擴充套件然後舉一反三。
如果S鎖的組合在兩個會話中是互相相容,那麼接下來的X鎖的組合就是互相排斥的。
那麼在兩個會話併發的場景下,死鎖的步驟如下:
mysql> create table dt1 (id int unique
Query OK, 0 rows affected (0.03 sec)
會話1:
begin;
select *from dt1 lock in share mode; --顯式共享鎖
會話2:
begin;
select *from dt1 lock in share mode; --顯式共享鎖
會話1:
insert into dt1 values(1); --阻塞
會話2:
insert into dt1 values(2); --觸發死鎖
所以上面的語句特點很明顯,插入的資料分別是1和2,看起來互補衝突也不行。
我們進度稍快一些,我們可能很少看到直接宣告share mode的方式,但是有很多時候由其他的場景會觸發,其中的一個主要原因就在於對於duplicate資料的檢查會開啟S鎖。這是比較特別的一點,需要注意。
按照這一點來擴充套件,很容易就可以擴充套件到3個會話中。
會話1只是負責插入一條資料,會話2,3也緊接著插入一條記錄(會話2,3自動提交),但是因為唯一性索引的檢查,會導致會話2和會話3都開啟了S鎖,因為相容,所以暫時還沒影響。如果會話1正常提交,會話2,3的檢查會生效,導致資料插入不了,違反唯一性約束,但是我們反其道而行,就可以用一個rollback來釋放鎖,緊接著會話2和會話3都會獲得S鎖成功,緊接著獲得X鎖,細節演算法就不說了。這個時候互相阻塞,導致會話3產生死鎖,會話2的資料插入依然會成功。
會話1:
begin;
insert into dt1 values(1);
會話2:
insert into dt1 values(1);
會話3:
insert into dt1 values(1);
會話1:
rollback;
看起來很精巧的小測試,但是裡面蘊含這大道理,比如按照這個思路,如果後面的兩個語句都是delete,也會觸發死鎖。有的時候我們可以正面來圖例,或者通過死鎖日誌來推理。給我的一個啟發是太極。
放在鎖的角度來理解就會好很多。
用一張不太形象的圖表示就是,左邊的部分是insert操作在會話1中,右邊的是在會話2和會話3中,都持有S鎖,然後會因為同樣的原因事務回滾後,他們的S鎖會升級為X鎖導致死鎖發生。
按照這個思路,我們可以繼續擴充套件出幾個場景。比如delete的方式。
按照這樣的思路,可以構建出很多的死鎖場景來。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-2148059/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL死鎖問題MySql
- MySQL 死鎖問題分析MySql
- MySQL鎖等待與死鎖問題分析MySql
- MySQL死鎖系列-線上死鎖問題排查思路MySql
- MySQL:一個死鎖分析 (未分析出來的死鎖)MySql
- 記一次 MySQL select for update 死鎖問題MySql
- MySQL:Innodb 一個死鎖案例MySql
- Mysql使用kill命令解決死鎖問題MySql
- 一次徹底講清如何處理mysql 的死鎖問題MySql
- 從一個死鎖問題分析最佳化器特性
- Oracle死鎖一例(ORA-00060),鎖表導致的業務死鎖問題Oracle
- 剖析6個MySQL死鎖案例的原因以及死鎖預防策略MySql
- 手把手教你分析解決MySQL死鎖問題MySql
- MySQL:死鎖一例MySql
- 【疑難系列】 一個看起來是資料庫死鎖的問題資料庫
- 一個有趣的鎖問題
- SpringBoot Seata 死鎖問題排查Spring Boot
- 記一個openwrt reboot非同步訊號處理死鎖問題boot非同步
- 故障解析丨一次死鎖問題的解決
- MySQL死鎖案例一(回滾導致死鎖)MySql
- 面試:什麼是死鎖,如何避免或解決死鎖;MySQL中的死鎖現象,MySQL死鎖如何解決面試MySql
- MySQL 死鎖和鎖等待MySql
- Python | 淺談併發鎖與死鎖問題Python
- MySQL:RR分析死鎖一列MySql
- 記一次神奇的Mysql死鎖排查MySql
- MySQL:一個特殊的問題MySql
- mysql insert into ... select的鎖問題MySql
- 測試MySQL鎖的問題MySql
- 線上問題排查:記一次 Redis Cluster Pipeline 導致的死鎖問題Redis
- 併發技術5:死鎖問題
- 解決Oracle死鎖問題步驟Oracle
- MySQL 死鎖解決MySql
- MySQL解決死鎖MySql
- MySQL:RR模式下死鎖一列MySql模式
- 記一次線上mysql死鎖MySql
- 一個“指令碼執行夯死”問題的分析指令碼
- mysql行鎖和死鎖檢測MySql
- Mysql 兩階段鎖和死鎖MySql
- 用個通俗的例子講一講死鎖