自动加锁与手动加锁
这是一个很好的澄清问题。简单直接的回答是:不全是自动的,有一部分需要你手动指定。
我把 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 MODE或FOR SHARE(MySQL 8.0+)。SELECT * FROM users WHERE id = 1 LOCK IN SHARE MODE; -
排他锁(X 锁):部分自动,部分手动。
- 自动:执行
UPDATE、DELETE、INSERT时,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 自动管理。