【mysql间隙锁何时出现及锁定范围】

发布于:2025-02-23 ⋅ 阅读:(15) ⋅ 点赞:(0)

MySQL的间隙锁(Gap Lock)是InnoDB引擎在可重复读(Repeatable Read)隔离级别下特有的锁机制,用于解决幻读问题。以下是间隙锁的触发条件及锁范围的分析:


一、间隙锁何时出现?

  1. 范围查询(Range Queries)
    当执行范围查询(如SELECT ... WHERE id BETWEEN X AND Y FOR UPDATE)时,InnoDB会对满足条件的已有记录加记录锁(Record Lock),同时对查询范围内的间隙(Gap)加间隙锁,防止其他事务插入新数据。

  2. 等值查询但记录不存在
    当执行等值查询(如SELECT ... WHERE id = Z FOR UPDATE),若目标记录不存在,InnoDB会对该值所在的间隙加间隙锁,阻止其他事务插入该值。

  3. 唯一索引的例外情况
    如果使用唯一索引且等值查询的记录存在,InnoDB只会加记录锁,不会加间隙锁(因为唯一性保证了无需防幻读)。


二、间隙锁的锁定范围

间隙锁锁定的是索引记录的间隙区间,具体规则如下:

1. 索引结构示例

假设某表索引值为 [10, 20, 30],索引间隙划分为:

  • (-∞, 10)
  • (10, 20)
  • (20, 30)
  • (30, +∞)
2. 不同场景的锁范围
  • 场景1:范围查询

    SELECT * FROM table WHERE id > 15 AND id < 25 FOR UPDATE;
    
    • 锁住间隙:(10, 20)(20, 30)(防止插入16~1921~29的值)。
    • 锁住记录:20(如果存在则加记录锁)。
  • 场景2:等值查询(记录不存在)

    SELECT * FROM table WHERE id = 25 FOR UPDATE;
    
    • 锁住间隙:(20, 30)(防止插入25)。
  • 场景3:唯一索引的等值查询(记录存在)

    SELECT * FROM table WHERE id = 20 FOR UPDATE;
    
    • 仅锁记录20(不加间隙锁)。

三、间隙锁与临键锁的关系

  • 临键锁(Next-Key Lock) = 记录锁 + 间隙锁,锁住左开右闭区间(如 (10, 20])。
  • 间隙锁是临键锁的“间隙部分”(如 (10, 20)),不包含右侧记录。

四、注意事项

  1. 仅作用于索引
    间隙锁基于索引,若无有效索引,InnoDB会退化为表锁。
  2. 显式关闭间隙锁
    通过降低隔离级别至读已提交(Read Committed),或设置innodb_locks_unsafe_for_binlog=1(不推荐),可禁用间隙锁。
  3. 死锁风险
    间隙锁可能因事务互相等待插入权限而导致死锁。

总结

间隙锁在可重复读级别下,通过锁定索引间隙防止幻读。其范围由查询条件和索引结构共同决定,需结合具体场景分析锁区间。理解间隙锁机制对优化高并发事务场景至关重要。


网站公告

今日签到

点亮在社区的每一天
去签到