MySQL 间隙锁 (Gap Lock)

5 阅读2分钟

间隙锁是 MySQL 中 InnoDB 存储引擎在特定隔离级别下使用的一种锁机制,主要用于防止幻读问题。下面我将详细解释间隙锁的概念、工作原理及其应用场景。

基本概念

间隙锁(Gap Lock)是一种锁定索引记录之间间隙的机制,而不是锁定记录本身。它锁定的是一个范围,防止其他事务在这个范围内插入数据。

例如,如果一个表中有索引值为 10、20、30 的记录,间隙锁可以锁定以下间隙:

  • 小于 10 的范围
  • 10 到 20 之间的范围
  • 20 到 30 之间的范围
  • 大于 30 的范围

工作原理

  1. 触发条件

    • 间隙锁仅在 RR(Repeatable Read)隔离级别下工作
    • 必须是通过索引条件检索数据
    • 不是等值查询(等值查询使用记录锁)
  2. 锁定范围: 间隙锁锁定的是索引记录之间的间隙,防止其他事务在间隙内插入记录

  3. Next-Key Lock: 实际上,InnoDB 通常使用的是 Next-Key Lock,它是记录锁(Record Lock)和间隙锁(Gap Lock)的组合,锁定索引记录及其之前的间隙

示例说明

假设有一个表 users 包含 id 列(主键),有值为 1, 5, 10 的记录:

执行:SELECT * FROM users WHERE id BETWEEN 3 AND 7 FOR UPDATE;

这个语句会锁定:

  • id 值 5 的记录(记录锁)
  • id 值 1 到 5 之间的间隙(间隙锁)
  • id 值 5 到 10 之间的间隙(间隙锁)

间隙锁的作用

  1. 防止幻读: 防止其他事务在查询范围内插入新记录,从而避免同一事务中的多次查询返回不同结果集

  2. 保证数据一致性: 确保事务执行期间,涉及范围的数据状态保持一致

间隙锁的问题

  1. 并发性能下降: 锁定范围而非具体记录,可能会导致不必要的锁冲突

  2. 死锁风险增加: 范围锁定增加了死锁的可能性

如何避免不必要的间隙锁

  1. 使用 READ COMMITTED 隔离级别(但会失去防止幻读的保障)
  2. 使用精确的索引和查询条件
  3. 在不需要严格隔离级别的场景,考虑使用乐观锁代替

总结

间隙锁是 InnoDB 在 RR 隔离级别下解决幻读问题的机制,通过锁定记录间隔防止其他事务插入数据。虽然它保证了事务隔离性,但可能会导致并发性能下降,需要根据具体业务场景权衡使用。