Skip to main content

自动加锁与手动加锁

这是一个很好的澄清问题。简单直接的回答是:不全是自动的,有一部分需要你手动指定

我把 InnoDB 的锁分为两类,方便你理解:

1. 完全自动的锁(你不需要任何操作)

这些锁由 InnoDB 内部自动管理,你无法干预,也不需要关心:

  • 意向锁(IS/IX):只要事务对某行加了 S 锁或 X 锁,InnoDB 自动在表级加上意向锁。
  • 间隙锁(Gap Lock):在 RR 隔离级别下,执行范围查询或对不存在的记录加锁时,自动生成。
  • 临键锁(Next-Key Lock):RR 隔离级别下默认的行锁算法,自动组合记录锁+间隙锁。
  • 插入意向锁:执行 INSERT 时,自动在间隙中生成。
  • 自增锁:向含 AUTO_INCREMENT 列的表插入时,自动加表级锁(可配置模式)。

这些锁你无法直接命令“加一个间隙锁”,它们是由 InnoDB 根据 SQL 和隔离级别自动决策并添加的。

2. 需要手动触发的锁(通过 SQL 语句)

  • 共享锁(S 锁)手动加。在 SELECT 后面加上 LOCK IN SHARE MODEFOR SHARE(MySQL 8.0+)。

    SELECT * FROM users WHERE id = 1 LOCK IN SHARE MODE;
  • 排他锁(X 锁)部分自动,部分手动

    • 自动:执行 UPDATEDELETEINSERT 时,InnoDB 会自动为涉及的行加 X 锁。
    • 手动:如果你只是想锁定某行以备后续更新,但暂时不修改,可以用 SELECT ... FOR UPDATE 手动加 X 锁。
  • 记录锁(Record Lock)自动,但依赖场景。当 InnoDB 使用唯一索引(如主键)等值查询并锁定记录时,临键锁会降级为记录锁。你无法直接说“加一个记录锁”,它是自动决策的结果。

总结表

锁类型自动 / 手动说明
意向锁 (IS/IX)完全自动内部机制,无需关注
间隙锁完全自动RR级别下自动出现
临键锁完全自动RR级别的默认锁算法
插入意向锁完全自动INSERT时自动
自增锁完全自动自增列插入时自动
记录锁自动(作为算法结果)唯一索引等值命中时,临键锁降级得到
排他锁 (X锁)自动(DML) / 手动(SELECT FOR UPDATE)DML自动加;查询需手动
共享锁 (S锁)手动必须用LOCK IN SHARE MODE

记忆要点

  • 所有跟“意向”、“间隙”、“临键”、“插入意向”、“自增”相关的锁,都是 InnoDB 内部自动行为,你不需要写任何语句去加。
  • 只有 S 锁,以及用于查询的 X 锁(SELECT FOR UPDATE)需要手动写出来。
  • DML(增删改)的 X 锁自动加,你不需要额外动作。

如果你在面试中被问到“这些锁是否需要手动加”,可以这样回答:除了共享锁和手动排他锁(SELECT FOR UPDATE)之外,其余锁均由 InnoDB 在内部根据隔离级别和 SQL 自动管理。