天天看點

innodb 鎖分裂繼承與遷移innodb行鎖簡介innodb 鎖分裂、繼承與遷移鎖分裂示例鎖繼承示例B樹結構變化與鎖遷移鎖繼承相關的BUG

行鎖類型

gap類型

每個行鎖由鎖類型和gap類型組成

例如:

lock_x|lock_ordinary 表示對記錄和記錄之前的間隙加排他鎖

lock_s|lock_gap 表示隻對記錄前的間隙加共享鎖

鎖的相容性:

值得注意的是,持有gap的鎖(lock_gap和lock_ordinary)與其他非lock_insert_intention的鎖都是相容的,也就是說,gap鎖就是為了防止插入的。

這裡的鎖分裂和合并,隻是針對innodb行鎖而言的,而且一般隻作用于gap類型的鎖。

鎖分裂

插入的記錄的間隙存在gap鎖,此時此gap需分裂為兩個gap

鎖繼承

删除的記錄前存在gap鎖,此gap鎖會繼承到要删除記錄的下一條記錄上

鎖遷移

b數結構變化,鎖資訊也會随之遷移. 鎖遷移過程中也涉及鎖繼承。

鎖分裂例子

這裡如果插入(3,3)沒有給(3,3)加lock_x|lock_gap,那麼其他連接配接插入(2,2)就可以成功

隔離級别repeatable-read

驗證:session 1執行insert into t1 values(1,1)發生了鎖等待,說明(2,2)上有gap鎖

隔離級别read-committed

驗證

session 1執行insert into t1 values(1)發生了鎖等待,說明(2)上有gap鎖

而實際在讀送出隔離級别上,insert into t1 values(1)應該可以插入成功,不需要等待的,這個鎖是否繼承值得商榷。

來看一個插入成功的例子

隔離級别serializable

驗證方法同read-committed。

b樹節點發生分裂,合并,删除都會引發鎖的變化。鎖遷移的原則是,b數結構變化前後,鎖住的範圍保證不變。

我們通過例子來說明

節點分裂

假設原節點a(infimum,1,3,supremum) 向右分裂為b(infimum,1,supremum), c(infimum,3,supremum)兩個節點

infimum為節點中虛拟的最小記錄,supremum為節點中虛拟的最大記錄

假設原節點a上鎖為3上lock_s|lock_oridnary,supremum為lock_s|lock_gap,實際鎖住了(1~)

鎖遷移過程大緻為:

1)将3上的gap鎖遷移到c節點3上

2)将a上supremum遷移繼承到c的supremum上

3)将c上最小記錄3的鎖遷移繼承到b的supremum上

遷移完成後鎖的情況如下(lock_update_split_right)

b節點:suprmum lock_s|lock_gap

c節點:3 lock_s|lock_orinary, suprmum lock_s|gap

遷移後仍然鎖住了範圍(1~)

節點向左分裂情形類似

節點合并

以上述節點分裂的逆操作來講述合并過程

b(infimum,1,supremum), c(infimum,3,supremum)兩個節點,向左合并為a節點(infimum,1,3,supremum)

其中b,c節點鎖情況如下

遷移流程如下(lock_update_merge_left):

1)将c節點鎖記錄3遷移到b節點

2)将b節點supremum遷移繼承到a的supremum上

節點向右合并情形類似

節點删除

如果删除節點存在左節點,則将删除節點符合條件的鎖,遷移繼承到左節點supremum上

否則将删除節點符合條件的鎖,遷移繼承到右節點最小使用者記錄上

參考lock_update_discard

bug#73170 二級唯一索引失效。這個bug觸發條件是删除的記錄沒有被purge, 鎖還沒有被繼承的。如果鎖繼承了就不會出現問題。

bug#76927 同樣是二級唯一索引失效。這個bug是鎖繼承機制出了問題。

繼續閱讀