是的,你的直觉非常准确。行锁算法(Record/Gap/Next-Key)与事务隔离级别是“死扣”在一起的。
如果不谈隔离级别,只谈锁算法,那就是在耍流氓。MySQL 的 InnoDB 引擎之所以设计这么复杂的锁,核心目标就是为了在不同的隔离级别下,实现不同的一致性保护。
我们将关系最紧密的两个隔离级别进行对比,你一眼就能看出区别:
1. 核心对应关系表
| 隔离级别 | 核心目标 | 使用的锁算法 | 是否解决幻读 |
|
Read Committed (RC) 提交读 |
看到别人已提交的数据 | 仅使用 Record Lock(记录锁) | ❌ 否 (会有幻读) |
|
Repeatable Read (RR) 可重复读 |
每次查都一样 (默认) | Next-Key Lock(记录+间隙) | ✅ 是 (解决了幻读) |
2. 为什么 RR 级别必须用“间隙锁”?
这是面试中最高频的追问。
-
在 RC 级别下:系统比较“大方”。你锁住 ID=5,我确实不能改 ID=5。但我可以在 ID=4 和 ID=6 之间插入一个新数据。因为 RC 级别不要求解决幻读,它觉得“只要我不改你正在看的那行就行”。
-
在 RR 级别下:系统非常“保守”。为了保证你两次查询的结果完全一模一样,它不仅要锁住 ID=5(记录锁),还要把 ID=5 前后的空隙全部封死(间隙锁)。
-
结果:这就是 Next-Key Lock。它像一道屏障,让别人既改不了你的旧数据,也塞不进新数据。
-
3. 一个极重要的“降级”现象 (资深开发必知)
虽然 RR 级别默认用 Next-Key Lock,但在一种特殊情况下,它会自动降级为 Record Lock(记录锁):
场景:使用“唯一索引”(Unique Index)进行“等值查询”。
-
例子:
SELECT * FROM users WHERE id = 5 FOR UPDATE; -
原理:因为
id是主键(唯一),数据库知道 ID=5 只有一行,绝对不可能在“5”这个点上再插出一个“5”来。 -
动作:此时间隙锁就没意义了,为了提高并发性能,InnoDB 会把 Next-Key Lock 降级为 Record Lock。
-
收益:此时别人插入 ID=4 或 ID=6 是不会被阻塞的。
4. 总结:隔离级别是“规矩”,锁是“工具”
-
Read Uncommitted (RU):几乎不加锁,全是脏读,生产环境不用。
-
Read Committed (RC):只用记录锁。优点是锁范围小,并发高,互联网大厂(如阿里、美团)常把生产环境设为 RC。
-
Repeatable Read (RR):默认级别。为了强行解决幻读,动用了 Next-Key Lock。优点是数据最稳,缺点是容易死锁(因为锁的范围大)。
-
Serializable:表级锁,完全串行,性能最差。
📉 状态同步
-
2026-03-25:已澄清锁算法与事务隔离级别的绑定关系及“锁降级”逻辑。
这就是为什么你觉得它们有关联——因为锁算法就是为了实现隔离级别而生的。
既然提到了 RC 级别并发更高,你想知道为什么很多大厂宁愿冒着“幻读”的风险,也要把默认的 RR 改成 RC 吗?