Mysql Innodb Lock

本文主要介紹Mysql中Innodb的鎖類型,主要參考自Mysql5.6手冊Innodb Lock一節,附上連接:https://dev.mysql.com/doc/refman/5.6/en/innodb-locking.html

本文內容:

Innodb中的鎖類型:

Innodb中鎖的主要實現:

Innodb中的鎖類型:

共享鎖和排它鎖

Innodb用共享鎖(s)和排它鎖(x)實現標準的行級鎖:

共享鎖(s):允許事務持有鎖讀取數據。

排它鎖(x):允許事務持有鎖修改和刪除數據。

如果一個事務T1持有一個數據表r行的共享鎖(s), 那麼事務T2對數據表r行的請求情況有以下兩種:

  1. 如果T2請求一個共享鎖(s),T2能立即獲取鎖, 那麼T1、T2都持有數據表r行的共享鎖(s);
  2. 如果T2請求一個排它鎖(x),那麼T2不能立即獲取鎖。

如果一個事務T1持有一個數據表r行的排它鎖(x),那麼事務T2不管請求的是哪種類型的鎖都不能立即獲得鎖,必須等待T1將該鎖釋放才能獲取。

意向鎖

Innodb支持多種粒度的鎖級別,包括行級鎖和表級鎖,表級鎖的主要有以下四種:

  1. 共享鎖(s):區別於行級共享鎖,該共享鎖持有表級鎖,其他與行級共享鎖類似;
  2. 排它鎖(x):區別於行級排它鎖,該排它鎖持有表級鎖,其他與行級排它鎖類似;
  3. 意向共享鎖(Is):表明事務意圖對錶某些行加共享鎖(s);
  4. 意向排它鎖Z(Ix):表明事務意圖對錶某些行加排它鎖(x)。

意向鎖的協議:

  1. 在事務獲取數據表某行的共享鎖(s)之前,它必須首先獲得該表的意向共享鎖(Is);
  2. 在事務獲取數據表某行的排它鎖(x)之前,它必須首先獲得該表的意向排它鎖(Ix)。

意向鎖有時候讓人難以理解,這裏簡單說一下意向鎖的作用:

   當我們想要對某個表加表級鎖時,首先要看當前表有沒有鎖並且鎖類型是否跟要加的鎖兼容。怎麼確定這個兼容性呢,最簡單的方式就是掃描全表,看看每一行的行鎖是否與要加的表鎖兼容,只要有一行不兼容,就不能加鎖。可以看出,當表比較大時這是一個十分耗時的過程,InnoDB提供了一種簡單的方式確定當前表持有行鎖的最強類型:意向鎖,意向鎖表明當前表持有行鎖的最強類型,當向表加表級鎖時,只需要看下是否與意向鎖兼容就可以了。意向鎖是InnoDB爲了行鎖和表鎖共存提供的一種優化手段,提高加表鎖的效率。

下面是一個表級鎖兼容性的總結:

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

一個事務的鎖請求只有兼容與存在的鎖類型才被允許,否則只能等待該表已存在鎖釋放。

以上是innodb中鎖的類型,在瞭解了innodb鎖的類型已經他們之間的相互關係之後,下面談談Innodb的鎖的實現:

記錄鎖

記錄鎖是一種加在唯一索引上的一種鎖,防止其他事務對該索引記錄進行修改和刪除操作。記錄鎖總是對索引記錄加鎖,假如該表沒有創建索引(mysql innodb 會隱式的創建一個聚簇索引),那麼記錄鎖會對該表的隱式索引加鎖。下圖展示了這種結構:

間隙鎖

間隙鎖是在兩個索引記錄之間間隙的鎖,或者在第一個索引記錄之前,最後一個記錄之後的間隙的鎖。阻止其他事務對兩個索引記錄之內的區間進行插入和修改操作。假如需要的數據上是唯一索引,那麼不要間隙鎖,而是用記錄鎖,假如需要的數據上沒有唯一索引,那麼使用間隙鎖對數據進行鎖定。還有值得注意的一點:事務T1持有了AB兩點間隙鎖,那麼事務T2仍然允許持有AB兩點的間隙鎖。

間隙鎖是一種在性能和併發之間的一種權衡,間隙鎖的主要目的是爲了防止對加鎖記錄之間插入數據,間隙鎖能被禁用,當設置事務的隔離級別爲不可重複讀時, 間隙鎖不再使用。

臨鍵鎖

臨鍵鎖是一種記錄鎖和該記錄之前間隙鎖的組合的鎖。用一個表說明:假設數據表中有3條記錄:[3,6,9],那麼臨鍵鎖有:

(負無窮,3],

(3,6],

(6,9],

(9, 正無窮)

在[3,6,9]這3條數據中,臨鍵鎖有以上四種, 可以看出,臨鍵鎖是記錄鎖和特殊間隙鎖的一種組合,在數據庫中,當設置數據庫的隔離級別爲可重複讀時,臨鍵鎖不在使用,在更高的隔離級別中,纔會使用臨鍵鎖。

自增鎖

AUTO-INC鎖是一種特殊的表級鎖,由事務插入具有AUTO_INCREMENT列的表中獲得。在最簡單的情況下,如果一個事務正在向表中插入值,則任何其他事務都必須等待自己向該表中插入,以便第一個事務插入的行接收連續的主鍵值,具體的算法由當前InnoDB使用的自增鎖模式確定

目前自增鎖模式算法有三種:傳統鎖定模式、連續鎖定模式和交叉鎖定模式,可以通過innodb_autoinc_lock_mode進行配置。

簡單插入:能夠提前確定插入行數的語句,例如:INSERT。

批量插入:不能提前確定插入行數的語句,例如:INSERT ... SELECT, REPLACE ... SELECT, and LOAD DATA。

  • 傳統鎖定模式:簡單插入和批量插入都使用AUTO-INC鎖,持有AUTO-INC鎖直到語句完成。
  • 連續鎖定模式:簡單插入通過在互斥鎖(一個輕量級鎖)的控制下獲得所需的自動增量值來避免表級的AUTO-INC鎖,該互斥鎖只在分配過程中保持,批量插入使用AUTO-INC鎖。
  • 交叉鎖定模式:指不管什麼情況都使用輕量級互斥的鎖,效率最高,但是複製只能使用row-basereplication,因爲statement-base replication會出現問題。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章