mysql記錄鎖(record lock),間隙鎖(gap lock),Next-key鎖(Next-key lock)


1. 什么是幻讀?
幻讀是在可重復讀的事務隔離級別下會出現的一種問題,簡單來說,可重復讀保證了當前事務不會讀取到其他事務已提交的 UPDATE 操作。但同時,也會導致當前事務無法感知到來自其他事務中的 INSERT 或 DELETE 操作,這就是幻讀。
關於行鎖我們要知道的
行鎖在 InnoDB 中是基於索引實現的,所以一旦某個加鎖操作沒有使用索引,那么該鎖就會退化為表鎖。
2. 鎖的分類
1)記錄鎖(Record Locks)
顧名思義,記錄鎖就是為某行記錄加鎖,它封鎖該行的索引記錄:

-- id 列為主鍵列或唯一索引列
SELECT * FROM table WHERE id = 1 FOR UPDATE; 

id 為 1 的記錄行會被鎖住。
需要注意的是:id 列必須為唯一索引列或主鍵列,否則上述語句加的鎖就會變成臨鍵鎖。
同時查詢語句必須為精准匹配(=),不能為 >、<、like等,否則也會退化成臨鍵鎖。
其他實現
在通過 主鍵索引 與 唯一索引 對數據行進行 UPDATE 操作時,也會對該行數據加記錄鎖:

-- id 列為主鍵列或唯一索引列
UPDATE SET age = 50 WHERE id = 1;

2)間隙鎖(Gap Locks)
間隙鎖基於非唯一索引,它鎖定一段范圍內的索引記錄。間隙鎖基於下面將會提到的Next-Key Locking 算法,請務必牢記:使用間隙鎖鎖住的是一個區間,而不僅僅是這個區間中的每一條數據。

SELECT * FROM table WHERE id BETWEN 1 AND 10 FOR UPDATE;

即所有在(1,10)區間內的記錄行都會被鎖住,所有id 為 2、3、4、5、6、7、8、9 的數據行的插入會被阻塞,但是 1 和 10 兩條記錄行並不會被鎖住。
除了手動加鎖外,在執行完某些 SQL 后,InnoDB 也會自動加間隙鎖,這個我們在下面會提到。

3)臨鍵鎖(Next-Key Locks)
Next-Key 可以理解為一種特殊的間隙鎖,也可以理解為一種特殊的算法。通過臨建鎖可以解決幻讀的問題。 每個數據行上的非唯一索引列上都會存在一把臨鍵鎖,當某個事務持有該數據行的臨鍵鎖時,會鎖住一段左開右閉區間的數據。需要強調的一點是,InnoDB 中行級鎖是基於索引實現的,臨鍵鎖只與非唯一索引列有關,在唯一索引列(包括主鍵列)上不存在臨鍵鎖。
假設有如下表:
MySql,InnoDB,Repeatable-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)。

4. 總結
①:InnoDB 中的行鎖的實現依賴於索引,一旦某個加鎖操作沒有使用到索引,那么該鎖就會退化為表鎖。
②:記錄鎖存在於包括主鍵索引在內的唯一索引中,鎖定單條索引記錄。
③:間隙鎖存在於非唯一索引中,鎖定開區間范圍內的一段間隔,它是基於臨鍵鎖實現的。
④:臨鍵鎖存在於非唯一索引中,該類型的每條記錄的索引上都存在這種鎖,它是一種特殊的間隙鎖,鎖定一段左開右閉的索引區間。


免責聲明!

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



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