插入意向鎖


一,共享/排它鎖(Shared and Exclusive Locks)

InnoDB並發為何這么高?》一文介紹了通用的共享/排它鎖,在InnoDB里當然也實現了標准的行級鎖(row-level locking),共享/排它鎖:

(1)事務拿到某一行記錄的共享S鎖,才可以讀取這一行;

(2)事務拿到某一行記錄的排它X鎖,才可以修改或者刪除這一行;

 

兼容互斥表如下:

          S          X

S      兼容      互斥

X      互斥      互斥

 

即:

(1)多個事務可以拿到一把S鎖,讀讀可以並行;

(2)而只有一個事務可以拿到X鎖,寫寫/讀寫必須互斥;

 

共享/排它鎖的潛在問題是,不能充分的並行,解決思路是數據多版本,具體思路在《InnoDB並發為何這么高?》里介紹過,這里不再深入展開。

 

二,意向鎖(Intention Locks)

InnoDB支持多粒度鎖(multiple granularity locking),它允許行級鎖與表級鎖共存,實際應用中,InnoDB使用的是意向鎖。

 

意向鎖是指,未來的某個時刻,事務可能要加共享/排它鎖了,先提前聲明一個意向。

 

意向鎖有這樣一些特點:

(1)首先,意向鎖,是一個表級別的鎖(table-level locking);

(2)意向鎖分為:

  • 意向共享鎖(intention shared lock, IS),它預示着,事務有意向對表中的某些行加共享S鎖

  • 意向排它鎖(intention exclusive lock, IX),它預示着,事務有意向對表中的某些行加排它X鎖

 

舉個例子:

select ... lock in share mode,要設置IS鎖

select ... for update,要設置IX鎖

 

(3)意向鎖協議(intention locking protocol)並不復雜:

  • 事務要獲得某些行的S鎖,必須先獲得表的IS鎖

  • 事務要獲得某些行的X鎖,必須先獲得表的IX鎖

 

(4)由於意向鎖僅僅表明意向,它其實是比較弱的鎖,意向鎖之間並不相互互斥,而是可以並行,其兼容互斥表如下:

          IS          IX

IS      兼容      兼容

IX      兼容      兼容

 

(5)額,既然意向鎖之間都相互兼容,那其意義在哪里呢?它會與共享鎖/排它鎖互斥,其兼容互斥表如下:

          S          X

IS      兼容      互斥

IX      互斥      互斥

畫外音:排它鎖是很強的鎖,不與其他類型的鎖兼容。這也很好理解,修改和刪除某一行的時候,必須獲得強鎖,禁止這一行上的其他並發,以保障數據的一致性。

 

三,插入意向鎖(Insert Intention Locks)

對已有數據行的修改與刪除,必須加強互斥鎖X鎖,那對於數據的插入,是否還需要加這么強的鎖,來實施互斥呢?插入意向鎖,孕育而生。

 

插入意向鎖,是間隙鎖(Gap Locks)的一種(所以,也是實施在索引上的),它是專門針對insert操作的。

畫外音:有點尷尬,間隙鎖下一篇文章才會介紹,暫且理解為,它是一種實施在索引上,鎖定索引某個區間范圍的鎖。

 

它的玩法是:

多個事務,在同一個索引,同一個范圍區間插入記錄時,如果插入的位置不沖突,不會阻塞彼此。

畫外音:官網的說法是

Insert Intention 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.

 

這樣,之前挖坑的例子,就能夠解答了。

 

在MySQL,InnoDB,RR下:

t(id unique PK, name);

 

數據表中有數據:

10, shenjian

20, zhangsan

30, lisi

 

事務A先執行,在10與20兩條記錄中插入了一行,還未提交:

insert into t values(11, xxx);

 

事務B后執行,也在10與20兩條記錄中插入了一行:

insert into t values(12, ooo);

 

(1)會使用什么鎖?

(2)事務B會不會被阻塞呢?

 

回答:雖然事務隔離級別是RR,雖然是同一個索引,雖然是同一個區間,但插入的記錄並不沖突,故這里:

  • 使用的是插入意向鎖

  • 並不會阻塞事務B

 

思路總結

(1)InnoDB使用共享鎖,可以提高讀讀並發;

(2)為了保證數據強一致,InnoDB使用強互斥鎖,保證同一行記錄修改與刪除的串行性;

(3)InnoDB使用插入意向鎖,可以提高插入並發;

 

結尾

假設不是插入並發,而是讀寫並發,又會是什么樣的結果呢?

 

MySQL,InnoDB,默認的隔離級別(RR)。

t(id unique PK, name);

 

數據表中有數據:

10, shenjian

20, zhangsan

30, lisi

 

事務A先執行,查詢了一些記錄,還未提交:

select * from t where id>10;

 

事務B后執行,在10與20兩條記錄中插入了一行:

insert into t values(11, xxx);

 

這里:

(1)會使用什么鎖?

(2)事務B會不會被阻塞呢?

 

 

最終結論:

(1)申請意向鎖的動作是數據庫完成的,就是說,事務A申請一行的行鎖的時候,數據庫會自動先開始申請表的意向鎖,不需要我們程序員使用代碼來申請。

(2)IX,IS是表級鎖,不會和行級的X,S鎖發生沖突。只會和表級的X,S發生沖突

行級別的X和S按照普通的共享、排他規則即可。所以之前的示例中第2步不會沖突,只要寫操作不是同一行,就不會發生沖突。

備注:  IX  意向排它鎖,IS 意向讀鎖


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM