愛可生 DBA 團隊成員,擅長故障分析、性能優化,個人博客:https://www.jianshu.com/u/a95ec11f67a8,歡迎討論。
*愛可生開源社區出品,原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。
重要改進
MySQL8.0 的死鎖日誌可以看到事務1持有的鎖信息了:
這對我們分析死鎖無疑是個很好的幫助,而在 MySQL5.7 是沒有這個信息的,一直飽受詬病:
注意事項
但是這在某些情況下可能會產生一些誤會,比如事務1持有鎖和等待鎖是同一個鎖:
爲什麼會出現這種情況?這是不是bug?
必須不是bug,我們來複現這一死鎖場景:
##設置RC隔離級別
CREATE TABLE `t2` (
`c1` int(11) NOT NULL,
`c2` int(11) DEFAULT NULL,
PRIMARY KEY (`c1`),
UNIQUE KEY `c2` (`c2`));
insert into t2 values(1,1),(5,4),(20,20);
-
session2 插入成功,對 c2 索引 10 這一記錄加 X Lock,即死鎖日誌中的 lock_mode X locks rec but not gap
; -
session1 插入時,發生唯一鍵衝突,需要對 c2 索引 10 這一記錄加 S Lock,帶 gap 屬性,即鎖的範圍爲 (4,10]。但是由於 session2 已經對記錄加了 X Lock,與 S Lock 互斥,所以必須等待 session 2 先釋放鎖,也就是死鎖日誌中的 lock mode S waiting
; -
session2 再次插入 9,在 (4,10] 範圍內,這個位置有 session1 的 gap 鎖(雖然還在鎖隊列中,沒有加上),插入意向鎖會被 gap 鎖阻塞,即死鎖日誌中的 lock_mode X locks gap before rec insert intention waiting
。session1、session2 互相等待,所以形成死鎖。
session1 等待獲取的鎖 S Lock 阻塞了 session2 將要獲取的鎖,這在 MySQL8.0 中就會顯示成 session1 持有的鎖,同時也是 session1 等待的鎖。就是這樣。
文章推薦:
技術分享 | show engine innodb status 中 Pages flushed up to 的含義
社區近期動態
本文分享自微信公衆號 - 愛可生開源社區(ActiontechOSS)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。