首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

深入理解 MySQL Gap Lock(間隙鎖)機制

     編輯:Java 綜合教學

什麼是 Gap Lock?

在 InnoDB 索引結構中,Gap(間隙)指可插入新記錄的空隙。Gap Lock 即加在間隙上的鎖;Next-Key Lock 則是「記錄鎖 + 該記錄前的間隙鎖」組合。

核心作用:防止幻讀

InnoDB 採用 Next-Key Locking 算法:鎖定掃描範圍內的索引記錄,同時封鎖範圍前的間隙,使其他事務無法在間隙插入新紀錄(插入時需獲取 Insert Intention Lock),從而在 REPEATABLE READ 隔離級別下避免幻讀。

何時會獲取 Gap / Next-Key Lock?

僅在 REPEATABLE READ 或 SERIALIZABLE 隔離級別下的特定操作:

  • Locking Reads(SELECT ... FOR UPDATE / LOCK IN SHARE MODE)
  • UPDATE / DELETE 且搜尋條件非唯一索引唯一查詢(範圍查詢、非唯一索引、全表掃描)

唯一索引 + 唯一條件僅鎖記錄本身,不鎖間隙。

實測驗證(非唯一索引 id)

表 tb2(id, c1),索引 tb2_idx1(id),資料:10、20、30。

Session 1:更新 id=20 不提交

BEGIN;
UPDATE tb2 SET c1=2 WHERE id=20;

Session 2:插入測試

INSERT INTO tb2 VALUES (9,4);   -- 成功(間隙 (-∞,10))
INSERT INTO tb2 VALUES (10,4);  -- 阻塞
INSERT INTO tb2 VALUES (19,4);  -- 阻塞
INSERT INTO tb2 VALUES (20,4);  -- 阻塞
INSERT INTO tb2 VALUES (21,4);  -- 阻塞
INSERT INTO tb2 VALUES (29,4);  -- 阻塞
INSERT INTO tb2 VALUES (30,4);  -- 成功(間隙 [30,+∞))

被鎖定範圍為 [10, 30),即 Next-Key Lock 覆蓋區間。

更新操作對比

UPDATE tb2 SET c1=4 WHERE id=10; -- 成功
UPDATE tb2 SET c1=4 WHERE id=20; -- 阻塞(記錄鎖衝突)
UPDATE tb2 SET c1=4 WHERE id=30; -- 成功

更新不獲取間隙鎖,僅阻塞同一記錄。

隔離級別差異

隔離級別Gap Lock 行為
READ COMMITTED不加間隙鎖,允許自由插入
REPEATABLE READ範圍查詢加 Gap/Next-Key Lock
SERIALIZABLE隱式將純 SELECT 轉為 LOCK IN SHARE MODE,同 RR

RR 下的「一致性讀」與「當前讀」

  • 一致性讀(普通 SELECT):讀取事務啟動時的快照,可避免幻讀。
  • 當前讀(Locking Read、UPDATE、DELETE):讀取最新提交版本,可見並發插入的新行,此時需靠 Gap Lock 防止幻讀。
注意:RR 下 UPDATE 會看到並發提交的修改,違反嚴格可重複讀語義,應用層需留意。

補充:RR vs RC 掃描加鎖差異

RC 下掃描不匹配記錄會釋放鎖(semi-consistent read);RR 則全程持有,對全表掃描 UPDATE 影響極大。詳細參考 何登成專欄。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved