MySQL(十五)】next-key lock

之前介紹過,sql標準中,rr級別並不能解決幻讀問題,那麼mysql是如何在rr級別解決幻讀問題的?

鎖協議

在非序列化隔離級別下,普通讀數據是快照讀,寫數據則要加X鎖,並且遵循兩段式鎖協議。也就是申請的鎖會一直佔用,直到事務提交。

幻讀問題

幻讀的定義有兩點需要注意:

1.幻讀只有使用鎖定讀纔可能出現,因爲普通讀使用的是非鎖定讀,會通過MVCC機制獲取到一致性視圖,是看不到新插入的行的;

2.只有讀到新增的數據才叫幻讀;

幻讀的影響:

1.如果只有行鎖的話,語義不正確,沒有鎖住新更新的行;

2.一致性,主庫和從庫的狀態可能不一致;

間隙鎖

上面的X鎖其實是行鎖,即對某一行數據加鎖;這個可以防止髒寫的發生,即鎖住已經存在的行,但是卻無法阻止新插入的行。間隙鎖是專門用來鎖住某一個間隙的,是開區間;

next-key lock

是間隙鎖+行鎖的組合,間隙鎖是行鎖key之前的那個間隙。比如行鎖要鎖住id=5的行,前一個值是id=1的行,那麼該行鎖對應的間隙就是(1,5),next-key lock就是(1,5]。

在rr級別下,默認的加鎖類型就是next-key lock。這樣可以防止新插入的數據導致的幻讀問題。因爲加的是next-key lock,所以鎖定的範圍變大了,相應得,併發性能也會降低,這需要權衡。

在其他級別下加的是行鎖。比如我們在rc級別下,就可以用鎖定讀復現幻讀問題:

事務一:

先執行一條鎖定讀,因爲是在rc級別,只給已經存在的id=1這一行加了行X鎖;

事務二:

也插入了一條gender=1的數據,因爲是新插入的,所以不受事務一加的行鎖阻塞;

事務一:

緊接着,事務一再執行一條鎖定讀,可以看到,讀到了新插入的數據,發生了幻讀;

所以,僅僅在rr級別下才會加next-key lock,在rc級別仍然是行鎖,是會有幻讀問題的;

next-key lock加鎖規則

這個比較複雜,需要結合具體的場景分析了:

訪問到的對象加next-key lock,直到不滿足條件的第一個值,這個值的鎖退化爲間隙鎖;如果是索引上的等值查詢,退化爲行鎖;

 

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