今天,將要介紹InnoDB另外三種:共享/排他鎖,意向鎖,插入意向鎖。併發
一,共享/排它鎖(Shared and Exclusive Locks)spa
《InnoDB併發爲什麼這麼高?》一文介紹了通用的共享/排它鎖,在InnoDB裏固然也實現了標準的行級鎖(row-level locking),共享/排它鎖:.net
(1)事務拿到某一行記錄的共享S鎖,才能夠讀取這一行;3d
(2)事務拿到某一行記錄的排它X鎖,才能夠修改或者刪除這一行;blog
其兼容互斥表以下:索引
S X事務
S 兼容 互斥ip
X 互斥 互斥get
即:it
(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會不會被阻塞呢?