一次mysql死鎖的發現

一次mysql死鎖的發現

這篇文章主要介紹了筆者在業務擴展的時候,設計欠妥,導致的死鎖,以及解決方案

本題難點在於下面這幾部分:

INSERT併發執行:在DDB的RC事務下面的併發插入
INSERT、DELETE併發執行:
INTENTION LOCK產生的原因與前提:

INSERT併發執行

對於INSERT操作來說,若發生唯一約束衝突,則需要對衝突的唯一索引加上S Next-key Lock。從這裏會發現,即使是RC事務隔離級別,也同樣會存在Next-Key Lock鎖,從而阻塞併發。

沒有唯一主鍵的併發操作

表結構如下:
image.png

單次insert事務,並不提交,模擬併發提交情況
image.png

另起一事務,提交多次insert
image.png

可以發現事務非常順利的被提交了,commit之後也發現數據很順利的提交上來了
image.png

唯一主鍵的併發操作

表結構如下:
image.png

單次insert事務,不提交,模擬併發提交情況
image.png

另一個事務提交時,發現表鎖
image.png

鎖日誌如下
image.png

INSERT、DELETE併發執行:

以無唯一主鍵表爲例

表結構如下:
image.png

單次delete事務,不提交,模擬併發提交情況(非主鍵刪除)
image.png

另一個事務執行insert的時候,發現表鎖,(無論userId是否在刪除隊列裏)
image.png

日誌如下:
image.png

單次delete事務,不提交(主鍵刪除)
image.png

另一個事務執行insert的時候,沒有發現表鎖,順利提交
image.png

INTENTION LOCK產生的原因與前提:

INSERT INTENTION LOCK,翻譯爲插入意向鎖,其實準確來說應該是INSERT INTENTION GAP LOCK。這個鎖類型在老版本的InnoDB中並不存在,後來是爲了優化插入性能而設計的。官方文檔中的說明如下:

Prior to inserting the row, a type of gap lock called an insert intention gap lock is set. This lock signals the intent to insert in such a way that multiple transactions inserting into the same index gap need not wait for each other if they are not inserting at the same position within the gap.

在RC事務隔離級別下,由於插入大部分是不需要等待的,所以這把鎖大部分時候也是不存在的。只有當發生鎖等待時,即插入的這條記錄下一條記錄next_rec有鎖,並且帶有GAP屬性,則這時需要對next_rec再加一個插入意向鎖。由於插入意向鎖和S/X Lock不兼容,因此需要等待。

在RC事務隔離級別下,雖然大多數插入操作是併發的,不會發生鎖等待。然而,由於唯一約束的存在,這時就需要加上插入意向鎖。而這也是上次死鎖案例問題產生的原因。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章