MySQL读已提交RC隔离级别减少间隙锁死锁原理
RC隔离级别默认不加间隙锁,只对命中行加记录锁,通过半一致性读减少锁竞争,且执行后立即释放未命中行的锁,降低了死锁概率。RR隔离级别默认加临键锁,扫描范围全加锁并保持到事务结束,死锁风险更高。但RC在唯一键冲突等场景下仍可能隐式加间隙锁。
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 完全与间隙锁绝缘——在唯一键冲突检查、外键约束校验等场景下,MySQL 仍会施加 gap lock,此时 INSERT 死锁仍有可能出现。但这只是极少数显式约束触发的特殊情况,与 RR 对每个范围查询都默认施加间隙锁的“地毯式覆盖”完全不可同日而语。
因此,真正需要警惕的并非“RC 到底有没有间隙锁”,而是以下两点:
- 不要在 RC 下想当然地认为“绝对安全”,而忽略了唯一索引冲突时隐式间隙锁的存在
- 不要因为应用层未能妥善处理不可重复读,就生硬地依靠加锁来硬扛,结果人为制造出新的死锁点
归根结底,间隙锁死锁的减少,本质上是将锁的默认行为从 RR 的保守全覆盖,转向了 RC 的按需最小化——但这一“按需”,最终仍需要你通过正确的 SQL 编写、合理的索引设计以及清晰的业务逻辑才能真正落地生效。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
SQL嵌套查询与窗口函数结合使用技巧
窗口函数不能直接用于WHERE、GROUPBY或HAVING,需先放入子查询或CTE计算,再在外层引用。典型错误如WHERE中写ROW_NUMBER(),需先用子查询生成编号再过滤。窗口函数排序必须显式写在OVER子句中,CTE比嵌套子查询更可靠。
phpMyAdmin导出的Laravel SQL文件生产环境报错原因
当使用phpMyAdmin工具导出SQL文件时出现报错,最常见的主要原因包括MySQL版本不匹配(例如8 0特有语法用于5 7)、时区设置语句导致错误、字符集编码不一致等。推荐的解决方法主要包括:注意需要仔细检查文件头部注释内容尤其是版本号,避免使用高版本特有语法,请务必删除SETtime_zone这行语句,并将字符集统一设置为utf8mb4编。
MySQL读已提交RC隔离级别减少间隙锁死锁原理
RC隔离级别默认不加间隙锁,只对命中行加记录锁,通过半一致性读减少锁竞争,且执行后立即释放未命中行的锁,降低了死锁概率。RR隔离级别默认加临键锁,扫描范围全加锁并保持到事务结束,死锁风险更高。但RC在唯一键冲突等场景下仍可能隐式加间隙锁。
MySQL批量更新表中特定字段值的方法
批量更新MySQL表字段,推荐使用CASEWHEN、INSERT…ONDUPLICATEKEYUPDATE或UPDATEJOIN,避免逐行循环。注意语法正确、类型统一,单次更新控制500-1000行,超10万行需分片提交并显式提交事务。
phpMyAdmin查询窗口为何无法执行超30秒SQL
phpMyAdmin超时源于$cfg[ ExecTimeLimit ]默认30秒,修改php ini无效,需在config inc php中设为0。MySQL的max_allowed_packet不足也会导致假性超时,需调整配置并重启服务。命令行导入可绕过Web层限制。
- 热门数据榜
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
相关攻略
2026-07-18 18:17
2026-07-18 18:16
2026-07-18 18:16
2026-07-18 18:16
2026-07-18 18:15
2026-07-18 18:15
2026-07-18 18:15
2026-07-18 18:14
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程

