詳解 MySql InnoDB 中的三種行鎖(記錄鎖、間隙鎖與臨鍵鎖)

前言

InnoDB 經過 MVCCNEXT-KEY Locks,解決了在可重複讀的事務隔離級別下出現幻讀的問題。MVCC 我先挖個坑,往後再細講,這篇文章咱們主要來談談那些可愛的鎖。算法

什麼是幻讀?

幻讀是在可重複讀的事務隔離級別下會出現的一種問題,簡單來講,可重複讀保證了當前事務不會讀取到其餘事務已提交的 UPDATE 操做。但同時,也會致使當前事務沒法感知到來自其餘事務中的 INSERTDELETE 操做,這就是幻讀sql

關於行鎖咱們要知道的

行鎖在 InnoDB 中是基於索引實現的,因此一旦某個加鎖操做沒有使用索引,那麼該鎖就會退化爲表鎖spa

可愛的鎖

記錄鎖(Record Locks)

顧名思義,記錄鎖就是爲某行記錄加鎖,它封鎖該行的索引記錄code

-- id 列爲主鍵列或惟一索引列
SELECT * FROM table WHERE id = 1 FOR UPDATE;
複製代碼

id 爲 1 的記錄行會被鎖住。索引

須要注意的是:id 列必須爲惟一索引列主鍵列,不然上述語句加的鎖就會變成臨鍵鎖事務

同時查詢語句必須爲精準匹配=),不能爲 ><like等,不然也會退化成臨鍵鎖(感謝評論區 @decodes 提醒)。string

其餘實現

在經過 主鍵索引惟一索引 對數據行進行 UPDATE 操做時,也會對該行數據加記錄鎖table

-- id 列爲主鍵列或惟一索引列
UPDATE SET age = 50 WHERE id = 1;
複製代碼

間隙鎖(Gap Locks)

間隙鎖基於非惟一索引,它鎖定一段範圍內的索引記錄間隙鎖基於下面將會提到的Next-Key Locking 算法,請務必牢記:使用間隙鎖鎖住的是一個區間,而不單單是這個區間中的每一條數據class

SELECT * FROM table WHERE id BETWEN 1 AND 10 FOR UPDATE;
複製代碼

即全部在(1,10)區間內的記錄行都會被鎖住,全部id 爲 二、三、四、五、六、七、八、9 的數據行的插入會被阻塞,可是 1 和 10 兩條記錄行並不會被鎖住。im

除了手動加鎖外,在執行完某些 SQL 後,InnoDB 也會自動加間隙鎖,這個咱們在下面會提到。

臨鍵鎖(Next-Key Locks)

Next-Key 能夠理解爲一種特殊的間隙鎖,也能夠理解爲一種特殊的算法。經過臨建鎖能夠解決幻讀的問題。 每一個數據行上的非惟一索引列上都會存在一把臨鍵鎖,當某個事務持有該數據行的臨鍵鎖時,會鎖住一段左開右閉區間的數據。須要強調的一點是,InnoDB行級鎖是基於索引實現的,臨鍵鎖只與非惟一索引列有關,在惟一索引列(包括主鍵列)上不存在臨鍵鎖

假設有以下表:
MySqlInnoDBRepeatable-Read:table(id PK, age KEY, name)

id age name
1 10 Lee
3 24 Soraka
5 32 Zed
7 45 Talon

該表中 age 列潛在的臨鍵鎖有:
(-∞, 10],
(10, 24],
(24, 32],
(32, 45],
(45, +∞],

事務 A 中執行以下命令:

-- 根據非惟一索引列 UPDATE 某條記錄
UPDATE table SET name = Vladimir WHERE age = 24;
-- 或根據非惟一索引列 鎖住某條記錄
SELECT * FROM table WHERE age = 24 FOR UPDATE;
複製代碼

無論執行了上述 SQL 中的哪一句,以後若是在事務 B 中執行如下命令,則該命令會被阻塞:

INSERT INTO table VALUES(100, 26, 'Ezreal');
複製代碼

很明顯,事務 A 在對 age 爲 24 的列進行 UPDATE 操做的同時,也獲取了 (24, 32] 這個區間內的臨鍵鎖。

不只如此,在執行如下 SQL 時,也會陷入阻塞等待:

INSERT INTO table VALUES(100, 30, 'Ezreal');
複製代碼

那最終咱們就能夠得知,在根據非惟一索引 對記錄行進行 UPDATE \ FOR UPDATE \ LOCK IN SHARE MODE 操做時,InnoDB 會獲取該記錄行的 臨鍵鎖 ,並同時獲取該記錄行下一個區間的間隙鎖

事務 A在執行了上述的 SQL 後,最終被鎖住的記錄區間爲 (10, 32)

總結

  1. InnoDB 中的行鎖的實現依賴於索引,一旦某個加鎖操做沒有使用到索引,那麼該鎖就會退化爲表鎖
  2. 記錄鎖存在於包括主鍵索引在內的惟一索引中,鎖定單條索引記錄。
  3. 間隙鎖存在於非惟一索引中,鎖定開區間範圍內的一段間隔,它是基於臨鍵鎖實現的。
  4. 臨鍵鎖存在於非惟一索引中,該類型的每條記錄的索引上都存在這種鎖,它是一種特殊的間隙鎖,鎖定一段左開右閉的索引區間。
相關文章
相關標籤/搜索