UPDATE 语句的锁机制

111 阅读1分钟

一、基于主键 / 索引的 UPDATE (不会阻塞的情况)

当 UPDATE 条件用主键 / 索引字段(比如 id 是主键)时:

  • 第一条 UPDATE id < 10:数据库会精准锁定 (-∞, 10) 范围的索引 / 数据,其他范围不受影响。
  • 第二条 UPDATE id > 15:锁定 (15, +∞) 范围 。
    由于锁定的索引范围不重叠,两条语句互不干扰,不会阻塞。
    本质是 索引锁(Record Lock、Gap Lock 等)的 “范围隔离” 特性,让不重叠的范围更新可并行。

二、非主键 / 索引字段的 UPDATE (会阻塞的情况)

若 UPDATE 条件用非索引字段(比如用 name 但 name 没建索引):

  • 数据库无法走索引,只能全表扫描找符合条件的行。

  • 全表扫描时,会对所有行加 “行级锁” (或因扫描逻辑触发间隙锁等),相当于把整个表 “锁住” 。

  • 此时,第一条 UPDATE 执行时会占住锁,第二条 UPDATE 要等锁释放才执行,就会阻塞
    核心是 无索引导致全表扫描,触发全局锁竞争,破坏并行性。

简单总结:

  • 走索引(主键 / 索引字段)  → 锁范围精准不冲突 → 不阻塞;
  • 不走索引(非索引字段)  → 全表扫描 + 全局锁 → 阻塞 。
    本质是 索引对锁范围的 “精准控制” vs 无索引时的 “全局锁竞争”  的区别~