【譯文】MySQL InnoDB 使用的鎖分析

InnoDB 使用的 鎖類型html

  共享鎖和排它鎖mysql

  意向鎖算法

  記錄鎖sql

  間隙鎖數據庫

  Next-key 鎖併發

  插入意向鎖高併發

  AUTO-INC 鎖性能

 

共享鎖和排他鎖spa

  InnoDB實現了倆個標準的行級鎖,共享鎖和排它鎖。code

    共享鎖容許持有者讀取一行

    排它鎖容許持有者更新或者刪除一行

  若是一個事物T1在 r 行持有一把共享鎖,則來自於不一樣的事物T2在 r 行上的鎖請求將按照以下方法處理:

    T2請求共享鎖能夠當即被受權,所以T1和T2都持有了在 r 行上的共享鎖

    T2請求排它鎖不能夠當即被受權。

  若是一個事物T1在 r 行持有一把排它鎖,則來自與不一樣事物T2在r上的任何鎖請求將不會當即被受權。

 

意向鎖

  InnoDB支持多粒度鎖:指容許表級鎖和行級鎖共存。爲了實如今多粒度級別上鎖,額外的鎖類型(意向鎖)被使用。意向鎖是一個表級鎖,它代表將來在那張表上會有哪種鎖類型(排他或者共享)被事物請求。

  InnoDB有倆種類型的意向鎖(假設事物未來會在某張表t上請求鎖):意向共享鎖,意向排他鎖。

  意向共享鎖:指事物意圖在表t上的某些行上加S鎖

  意向排它鎖:指事物意圖在表t上的某些行上加X鎖

  意向鎖協議描述以下:

    事物在表t上的一行上加S鎖以前,他必須獲取IS鎖或者在t上更強的鎖(指表級鎖)

    事物在表t上的一行上加X鎖以前,他必須獲取IX鎖

  上述鎖規則協議能夠方便的歸納以下的兼容性矩陣:

  X IX S IS
X Conflict Conflict Conflict Conflict
IX Conflict Compatible Conflict Compatible
S Conflict Conflict Compatible Compatible
IS Conflict Compatible Compatible Compatible

    注:意向鎖是MySQL本身自動處理,爲了解決表級鎖和行級鎖的衝突,即提前檢測鎖衝突。

S、X、IS、IX鎖兼容性矩陣爲何是這樣子呢?

一、意向鎖之間彼此不會衝突,由於它們都只是「有意」,而不是真幹,因此是能夠兼容的。在加行鎖以前,會使用意向鎖判斷是否衝突;
二、IX和X的關係等同於X和X之間的關係,爲何呢?由於事務得到了IX鎖,接下來就有權利獲取X鎖,這樣就會出現兩個事務都獲取X鎖的狀況,這和咱們已知的X鎖和X鎖之間互斥是矛盾的;
三、S和IS、X和IS、IX和IS也能夠由此推導出來。

  一個鎖被授予一個事物,是在該鎖與事物已獲取的鎖兼容的時候,而不是與現有鎖衝突的時候。事物等待直到衝突的鎖被釋放。若是一個鎖請求與現有的鎖衝突,而且由於死鎖不能被授予,一個錯誤會發生,MySQL本身決定哪一個事物回滾

 

  所以意向鎖不阻塞任何事物,除了全表鎖請求。IX鎖和IS鎖是用來代表某我的或者事物正在持有鎖或者將要持有鎖。

 

記錄鎖

  一個記錄鎖是在索引記錄上的鎖,僅鎖住一行。例如:SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; 阻止任何其餘事物插入、更新、刪除c1=10的行,前提是c1有索引。

  記錄鎖鎖住的只是記錄的索引「記錄」,及時一個表沒有定義任何索引,InnoDB也會默認建立一個聚簇索引,並用來加鎖。

  不符合where條件的記錄鎖會被釋放。

 

間隙鎖

  間隙鎖是指鎖住索引記錄之間的空隙(並不鎖住索引記錄,即開區間),或者明確指定索引記錄的第一個和最後一個,例如:SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE; 阻止任何其餘事物的插入、更新和刪除

  Gap能夠僅有一個值,多個值或者爲空。

  Gap鎖是在性能和併發度上權衡的結果,並被某些事物隔離級別使用。

  Gap鎖在一些使用惟一索引的來檢索惟一行的語句中是沒有必要的,由於索引的結果是惟一的,沒有間隙,不會妨礙其餘會話(事物)插入記錄。注,那些語句中包含惟一索引和二級索引的仍然適用Gap鎖。

  值得注意的是,在不一樣事物中,鎖衝突能夠發生在同一個間隙裏,例如一個事物A持有一把共享GAP鎖在Gap間隙中,同時事物B持有一把排他的Gap鎖,倆個Gap屬於同一個。

    注,舉一個例子,假設數據庫存在id爲1,2,3,5,7;事物1:select * from student where id between 3 and 9 for update; 事物2:select * from student where id = 8; 倆個事物共享(7-9)這個間隙鎖,但互不影響。

    衝突Gap被容許的緣由是若是一個記錄從索引中被清除了,不一樣事物在這個記錄上的Gap鎖必須合併。

    注:上述狀況未實驗成功,首先是不太明白其意思,其次是若是刪除索引記錄,意味着加X鎖,然而這個鎖的排他性已是衝突了,並不能驗證成功。若是有人直銷煩請告知,不勝感激!

  Gap鎖在InnoDB中是純抑制做用,意思是Gap鎖僅阻止其餘事物插入這個gap間隙,他們不阻止不一樣的事物在相同的gap上獲取gap鎖。所以,GapX鎖和GapS鎖有相同的效果。

  Gap鎖能夠被禁用,經過設置RC隔離級別,或者啓用 innodb_locks_unsafe_for_binlog系統變量(當前已標記爲了棄用),此時,在檢索和掃描的時候Gap鎖被禁用,且僅被用做外鍵檢查和重複值檢測。

注:當用惟一索引時,三種方法可能產生間隙鎖:

  1. 惟一檢索值不存在,此時會在索引中尋找「最小區間」加間隙鎖;
  2. between and 條件篩選肯定索引間隙加鎖;
  3. 檢索值和比較操做符,例如大於小於檢索值(此時符合的記錄也會加記錄鎖,不只僅是間隙鎖)

  

 

Next-key Locks

  Next-key鎖是記錄鎖和Gap鎖的結合。

  InnoDB 執行行級鎖,所以,當檢索或掃描表索引時,他設置S或者X鎖到遇到的索引記錄上。所以,行級鎖其實是記錄鎖,一個索引記錄上的next-key鎖,一樣影響索引記錄以前的gap。就是說next-key鎖是一個記錄鎖,加上一個gap(記錄以前)鎖。

  假設索引裏面有10,11,13,20。則可能的next-key鎖是:

(negative infinity, 10]
(10, 11]
(11, 13]
(13, 20]
(20, positive infinity)

  默認地,InnoDB提供的事物隔離級別是RR,此時InnoDB使用的是next-key鎖,在檢索和掃描的時候。以阻止幻讀。next-key在使用惟一索引時會降級爲記錄鎖,提升併發度。

 

插入意向鎖(一種特殊的gap鎖):

  插入意向鎖是當插入操做執行時,設置的一種特殊的gap類型鎖。這個lock標誌一種插入行爲:若是每一個事物插入gap中的位置不同時在多事物插入相同的gap狀況不須要互相等待。這主要是提升併發插入效率。

 

AUTO-INC鎖

  該鎖類型是一種特殊的表級鎖,在事物插入自動增加字段時使用。若是一個事物插入列值(自動增加列)到表中,任何其餘的事物必須等待,所以插入的字段纔會是連續的值。

   innodb_autoinc_lock_mode配置選項,控制自動增加鎖使用的算法,它容許你選擇插入操做時,如何來權衡可預測的自動增加值和最大併發度

 

注:

  排它鎖和共享鎖是指鎖的性質,意圖鎖是意圖。

  記錄鎖和Gap鎖是鎖的範圍,這就會出現是在必定的範圍加特定性質的鎖的問題。

相關文章
相關標籤/搜索