间隙锁(Gap Lock)是数据库在可重复读(Repeatable Read)隔离级别 下(以InnoDB引擎为例),为防止幻读而引入的一种行级锁机制(不需要开发人员主动 "显式添加")。它锁定的是索引记录之间的"间隙",而非具体的索引记录本身,目的是阻止其他事务在该间隙中插入新的记录,从而保证事务读取数据的一致性。
一、间隙的定义
"间隙"指的是索引记录之间的空白区域,包括:
- 两条相邻索引记录之间的区间(如索引值10和20之间的间隙);
 - 第一条索引记录之前的区间(如小于最小索引值5的间隙);
 - 最后一条索引记录之后的区间(如大于最大索引值30的间隙)。
 
例如,表中已有索引值为 10、20、30 的记录,那么间隙包括:
(-∞, 10)(10, 20)(20, 30)(30, +∞)
二、间隙锁的触发场景
当事务对某条记录加锁时(如SELECT ... FOR UPDATE或UPDATE),若使用范围条件 或等值条件但未命中记录,InnoDB会对符合条件的索引间隙加锁。
示例1:范围查询加锁
假设有表 user(id, age),age 是索引列,数据如下:
| id | age | 
|---|---|
| 1 | 10 | 
| 3 | 20 | 
| 5 | 30 | 
事务A执行:
            
            
              sql
              
              
            
          
          -- 范围查询,锁定age在15~25之间的记录及间隙
SELECT * FROM user WHERE age BETWEEN 15 AND 25 FOR UPDATE;
        此时,事务A会锁定 age 在 (10, 30) 之间的间隙(因为15~25落在10和30之间)。
其他事务若尝试插入 age=18 或 age=22 的记录,会被阻塞,直到事务A提交释放锁。
示例2:等值查询未命中记录
事务A执行:
            
            
              sql
              
              
            
          
          -- 等值查询,但表中没有age=25的记录
SELECT * FROM user WHERE age = 25 FOR UPDATE;
        此时,InnoDB会锁定 age=25 可能插入的间隙(即(20, 30)),其他事务插入 age=25 会被阻塞。
三、间隙锁的特点
- 只锁间隙,不锁记录:间隙锁不会阻止对已有记录的修改,仅阻止新记录插入。
 - 与隔离级别相关 :仅在 可重复读(RR) 级别生效,读已提交(RC)及以下级别不会使用间隙锁(因此RC级别可能出现幻读)。
 - 可能导致死锁 :多个事务对重叠的间隙加锁时,可能因等待对方释放锁而产生死锁。
- 例如:事务A锁定
(10, 20),事务B锁定(15, 25),两者都想插入age=18的记录,会相互等待对方释放锁。 
 - 例如:事务A锁定
 
四、间隙锁与其他锁的关系
- 记录锁(Record Lock) :锁定具体的索引记录(如
age=20的记录)。 - 临键锁(Next-Key Lock) :InnoDB的默认行锁方式,是"记录锁+间隙锁"的组合,锁定索引记录及其之前的间隙(如锁定
age=20的记录,同时锁定(10, 20)的间隙)。 
五、间隙锁的核心作用
解决幻读问题。幻读是指:一个事务在多次查询中,由于其他事务插入了新数据,导致前后查询结果不一致(多出原本不存在的记录)。
间隙锁是临键锁的一部分,临键锁锁定的范围是一个左开右闭区间 ,例如 (10, 20],其中:
- 记录锁 :锁定具体的索引记录(如 
id=20),阻止其他事务修改或删除该记录。 - 间隙锁 :锁定索引记录之间的空白区域(如 
(10, 20)),阻止其他事务在该区间插入新记录。 
采用临键锁确保了在事务执行期间,查询范围内的所有可能插入新数据的位置都被锁定,从而避免幻读。