Next-Key Lock 详解

Next-Key Lock 详解
Next-Key Lock 是 InnoDB 存储引擎在可重复读(RR)隔离级别下实现的一种锁机制,结合了 记录锁(Record Lock) 和 间隙锁(Gap Lock),用于解决幻读问题。以下是其核心机制与作用的详细分析:

  1. Next-Key Lock 的定义与组成
    Next-Key Lock = 记录锁(锁定单个行) + 间隙锁(锁定范围),形成一个 左开右闭的区间(例如 (5,8])。
    记录锁(Record Lock):锁定索引记录本身(若存在)。
    间隙锁(Gap Lock):锁定索引记录之间的间隙(不包含记录本身),阻止其他事务在范围内插入新数据。
    锁定范围:例如索引值 1,3,5,8,11,其 Next-Key Lock 区间为 (5,8],并可能扩展到相邻间隙(如 (8,11])。

  2. 加锁规则与优化策略
    InnoDB 对 Next-Key Lock 的加锁遵循以下规则:
    基本单位:默认加锁单位是 Next-Key Lock(左开右闭区间)。
    访问对象加锁:仅对查询过程中实际访问的索引记录加锁。
    优化 1(唯一索引等值查询):若命中唯一索引的等值查询,Next-Key Lock 退化为 行锁(仅锁定单行)。
    示例:SELECT * FROM user WHERE id=5 FOR UPDATE,若 id 是唯一索引,则仅锁 id=5。
    优化 2(非等值查询):若索引等值查询的最后一个值不满足条件,Next-Key Lock 退化为 间隙锁(仅锁定范围)。
    示例:查询 WHERE a=10,但索引中最大值为 8,则锁定 (8, +∞) 的间隙。

  3. 解决幻读的机制
    幻读指同一事务中多次查询同一范围时,出现新插入的行。Next-Key Lock 通过以下方式避免幻读:
    锁定范围与记录:对查询涉及的索引记录及其间隙加锁,阻止其他事务插入或修改该范围内的数据。
    示例场景:
    事务 A 执行 SELECT * FROM t WHERE a=8 FOR UPDATE,锁定 (5,8] 和 (8,11]。
    事务 B 尝试插入 a=6 或 a=9 时会被阻塞,直到事务 A 提交。

  4. 实际应用与锁冲突分析
    案例 1:范围查询的锁范围
    表数据:a=1,3,5,8,11。
    事务 A 执行 SELECT * FROM t WHERE a=8 FOR UPDATE
    锁定区间 (5,8](Next-Key Lock)和 (8,11](辅助索引的下一个间隙锁)。
    阻塞操作:插入 a=6,7,9,10 均被阻塞;插入 a=12 不受影响。
    案例 2:唯一索引的退化解锁
    表结构:主键 name,辅助索引 id。
    事务 A 执行 SELECT * FROM t WHERE id=5 FOR UPDATE:
    若 id 是唯一索引,退化为行锁,仅锁定 id=5,不影响其他范围插入。

  5. 与事务隔离级别的关系
    可重复读(RR):默认使用 Next-Key Lock,防止幻读。
    读已提交(RC):不使用 Next-Key Lock,可能允许幻读。
    可串行化(Serializable):通过表级锁实现严格隔离,但牺牲并发性

Next-Key Lock 范围确定机制详解

  1. 锁定区间逻辑分析
    在示例中,表 t 的辅助索引列 a 的值为 1,3,5,8,11,事务 A 执行 SELECT * FROM t WHERE a=8 FOR UPDATE,触发了 Next-Key Lock 和辅助索引的间隙锁。具体锁定范围如下:
    (1) Next-Key Lock 的基本规则
    Next-Key Lock 的默认锁定范围是 左开右闭区间(例如 (5,8]),包含当前查询值和其左侧的间隙。
    辅助索引的特殊性:InnoDB 不仅会锁定查询值所在的区间,还会对 下一个键值的间隙加锁(如 (8,11])以防止幻读
    (2) 具体锁定范围推导
    主区间锁定:
    查询 a=8,其相邻的索引值为 5 和 11。
    Next-Key Lock 锁定 (5,8](包含 a=8 的当前值和左侧间隙 5 < a ≤ 8) 1 3。
    辅助索引的下一个间隙锁定:
    为防止在 a=8 和 a=11 之间插入新数据,InnoDB 额外锁定 (8,11](左开右闭区间)
  2. 阻塞操作的验证
    (1) 被阻塞的插入操作
    插入 a=6,7:属于 (5,8] 区间,被 Next-Key Lock 阻塞。
    插入 a=9,10:属于 (8,11] 区间,被辅助索引的间隙锁阻塞。
    (2) 未被阻塞的插入操作
    插入 a=12:属于 (11, +∞) 区间,不在锁定范围内,因此允许插入。
  3. 锁范围的示意图
索引值分布:1, 3, 5, 8, 11  
锁定区间:
          (5,8] ← Next-Key Lock(主区间)  
          (8,11] ← 辅助索引的下一个间隙锁  
阻塞插入范围:5 < a ≤ 11  
允许插入范围:a ≤5 或 a >11
  1. 锁机制的核心目的
    解决幻读:通过锁定当前值和相邻间隙,阻止其他事务在查询范围内插入新数据 2 3。
    辅助索引的特殊处理:由于辅助索引可能存在重复值,需额外锁定下一个间隙以确保数据一致性
posted @ 2025-02-25 16:45  lipu123  阅读(473)  评论(0)    收藏  举报