ZBLOG

mysql中GAP锁有什么作用,解决了什么问题

在 MySQL 的 InnoDB 存储引擎中,GAP 锁(间隙锁) 是事务隔离级别为 可重复读(REPEATABLE READ) 时引入的一种锁机制,主要用于解决幻读(Phantom Read)问题。以下是它的详细作用及解决的问题:


1. GAP 锁的作用

  • 锁定一个范围,但不包括记录本身
    GAP 锁会锁定索引记录之间的“间隙”(即两个索引值之间的区间),或者第一个索引值之前或最后一个索引值之后的区间。例如:
    • 如果表中有索引值 [10, 20, 30],那么可能的间隙区间包括:(-∞, 10)(10, 20)(20, 30)(30, +∞)
  • 防止其他事务在间隙中插入新数据
    当一个事务对某个范围加 GAP 锁后,其他事务无法在这个范围内插入新的索引记录(但允许修改或删除已有的记录)。

2. 解决的问题:幻读(Phantom Read)

  • 幻读的定义
    在同一事务中,多次执行相同的查询,但每次返回的结果集不同(其他事务插入了新数据导致新增了满足条件的行)。
  • GAP 锁如何防止幻读
    通过锁定可能被插入新数据的“间隙”,确保其他事务无法在当前事务查询的范围内插入新数据,从而保证多次查询结果的一致性。

3. GAP 锁的触发场景

  • 基于范围的查询(WHERE 条件使用范围条件)
    例如 SELECT * FROM table WHERE id BETWEEN 10 AND 20 FOR UPDATE;
    此时会锁定 [10, 20] 这个区间内的所有间隙(即使某些索引值不存在)。
  • 等值查询针对不存在的记录
    例如 SELECT * FROM table WHERE id = 15 FOR UPDATE;
    如果 id=15 不存在,则会锁定 15 所在的间隙(比如锁定 (10,20)),防止其他事务插入 id=15

4. GAP 锁的兼容性

  • GAP 锁之间是兼容的:多个事务可以同时对同一个间隙加 GAP 锁。
  • GAP 锁和记录锁(行锁)可以组合成 Next-Key Lock(默认的行锁机制),同时锁定记录和间隙。

5. 注意事项

  • 仅存在于可重复读(REPEATABLE READ)隔离级别
    在 READ COMMITTED 隔离级别下,InnoDB 不会使用 GAP 锁。
  • 仅针对索引生效
    如果操作没有使用索引,InnoDB 会退化为表锁(包括间隙),但性能较差。
  • 可能影响并发插入性能
    因为 GAP 锁会阻止在锁定区间内插入新数据,在高并发写入场景中可能需要优化索引或调整隔离级别。

6.示例说明

假设表 t 有索引列 id,现有数据为 [1, 5, 10]

-- 事务A执行:
BEGIN;
SELECT * FROM t WHERE id BETWEEN 5 AND 10 FOR UPDATE;

此时会锁定区间 (5,10](Next-Key Lock),包括:

  • 记录锁锁定 id=5id=10
  • GAP 锁锁定区间 (5,10)

此时如果事务B尝试插入 id=7

-- 事务B会被阻塞:
INSERT INTO t (id) VALUES (7);

直到事务A提交后,事务B才能继续执行。


总结

GAP 锁是 InnoDB 在可重复读隔离级别下实现幻读控制的核心机制之一。它通过锁定索引间隙来防止其他事务插入新数据,从而保证查询结果的一致性。但需注意其可能对并发写入性能的影响。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=24183

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?