最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
为什么MySQL读已提交(RC)隔离级别能减少间隙锁死锁?
时间:2026-07-14 10:03:46 编辑:袖梨 来源:一聚教程网
RC默认不加间隙锁,RR默认加临键锁;RC通过半一致性读和早释放锁降低死锁概率,仅对命中行加锁,而RR对扫描范围全加锁并持至事务结束。
RC 默认不加间隙锁,RR 默认加临键锁
间隙锁(gap lock)是 RR 隔离级别为防止幻读而自动启用的机制,它不仅锁住匹配的行,还锁住索引记录之间的“间隙”。比如表中有 id 值 1、5、10,执行 UPDATE t SET name='x' WHERE id BETWEEN 3 AND 8,RR 会锁住 (1,5] 和 (5,10) 这两个间隙,导致其他事务无法插入 id=4 或 id=6;而 RC 只对实际命中的 id=5 加 record lock,间隙完全开放。
死锁常发生在多个事务按不同顺序尝试获取同一组间隙锁时。RC 下没有这种跨间隙的锁竞争,自然大幅降低死锁概率。
RC 的半一致性读让 UPDATE 不盲目加锁
当 UPDATE 扫描到已被其他事务加了 X lock 的行时,RC 会触发半一致性读(semi-consistent read):先读该行最新已提交版本,再判断是否满足 WHERE 条件;只对满足条件的行才尝试加锁。RR 则不管内容是否匹配、是否被锁,只要扫描到就直接加 next-key lock 并阻塞。
这意味着:
- 无索引查询在 RC 下最多只锁住最终更新的几行
- 同样语句在 RR 下可能锁住整个扫描范围(比如全表扫描 + 全表间隙锁),极易引发锁等待链和死锁
RC 锁释放更早,减少锁持有时间重叠
RC 中 UPDATE 或 DELETE 语句执行完即释放所有未命中行的锁;RR 会把所有扫描过的行(包括不满足 WHERE 的)都加上 next-key lock,并一直持有到事务结束。
例如:UPDATE users SET status=2 WHERE created_at > '2026-01-01' 在 RR 下可能锁住几千行(哪怕只改 3 行),其他事务更新任意一行都会卡住;RC 只锁那 3 行,其余扫描行锁立刻释放——锁持有窗口窄,事务间冲突窗口自然小。
RC 下 INSERT 死锁仍可能发生,但诱因完全不同
RC 并非完全无间隙锁:在唯一键冲突检查、外键约束校验等场景下,仍会加 gap lock,此时也可能发生 INSERT 死锁。但这属于极少数显式约束场景,而非 RR 那样对每个范围查询都默认启用。
所以真正要警惕的不是“RC 有没有间隙锁”,而是:
- 是否在 RC 下误以为“绝对安全”,忽略了唯一索引冲突时的隐式间隙锁
- 是否在应用层没处理好不可重复读,反而靠加锁硬扛,人为引入新死锁点
间隙锁死锁的减少,本质是把锁的“默认行为”从 RR 的保守覆盖,转向 RC 的按需最小化——但这个“按需”,得靠你写对 SQL、建好索引、理清业务逻辑才能兑现。
相关文章
- 繁花漫画正版直达链接在哪 07-14
- 神探杰克鼠进口货物支线任务攻略 07-14
- 掌上衡水app如何查看资讯 07-14
- claude-skills 是什么?355 个 Claude Code 技能包合集介绍(2026更新版) 07-14
- 《深海迷航2:异星水域》快速解锁蝌蚪号攻略-详细步骤解析 07-14
- 蚂蚁庄园小课堂2026年1月16日最新题目答案 07-14