当前位置: 首页
数据库
mysql为什么RC级别在高并发下更受欢迎_分析其对死锁与并发的优化

mysql为什么RC级别在高并发下更受欢迎_分析其对死锁与并发的优化

热心网友 时间:2026-05-04
转载

RC降低死锁概率的根本原因是默认不使用间隙锁,仅对命中行加记录锁,锁范围更小、冲突更少;而RR对范围条件自动加Next-Key锁,易引发循环等待死锁。

mysql为什么RC级别在高并发下更受欢迎_分析其对死锁与并发的优化

RC 隔离级别为什么能降低死锁概率

说到底,RC级别降低死锁概率的核心秘诀,就在于它“不轻易动用”间隙锁(Gap Lock)——除了检查唯一键或外键冲突这类少数特定场景。对比之下,在RR级别里,一句 UPDATE WHERE age > 25 这样的范围更新,InnoDB会默认加上Next-Key Lock(记录锁+间隙锁),把整个区间都锁住。而在RC级别下,它只锁定实际被修改的那些行,锁的范围大大缩小,事务之间“撞车”的可能性自然就降低了。

一个典型的死锁链条是这样的:事务A锁住了(10, 20)这个间隙,事务B锁住了(20, 30)这个间隙,然后它们都试图往中间插入一条id=25的记录,结果就是互相等待,直接卡死。但在RC级别下,这些间隙本身不会被锁定,不同事务的插入意向锁(Insert Intention Lock)之间是兼容的,因此这类因争夺“空隙”而引发的循环等待,基本可以避免。

几个关键差异,可以这样理解:

  • 在RR级别下,执行SELECT ... FOR UPDATE或带范围条件的UPDATE时,InnoDB会自动升级为Next-Key Lock。
  • 而在RC级别下,执行同样的SQL,通常只加记录锁(Record Lock)。当然,如果涉及唯一索引冲突检查,它仍然会加S型的Next-Key Lock来做重复性校验。
  • RC级别还能减少MVCC版本链的维护开销,尤其是在写多读少的场景里,undo log的清理压力会更小一些。
  • 最后要提醒一点:间隙锁缺失不等于完全没有锁。遇到外键约束或者唯一键冲突检测时,Gap Lock依然会被触发,这个细节常常被忽略。

RC 下 INSERT 死锁的真实诱因

很多人可能以为,切换到RC级别就彻底告别INSERT死锁了,其实不然。真正的陷阱,往往藏在唯一键冲突和主键冲突的锁行为里——在这些场景下,RC和RR的加锁策略是一致的。

举个例子,两个事务并发执行这样一条语句:

INSERT INTO users (id, email) VALUES (100, 'a@b.com');

如果email字段是唯一索引,并且表中已经存在一条email='a@b.com'的记录,那么两个事务都会尝试对这条已存在的记录加上S型的Next-Key Lock(目的是做冲突检测)。紧接着,它们又都会试图插入自己的新行,这就形成了X锁与S锁的互斥,死锁一触即发。

这里有几个关键点需要把握:

  • 使用INSERT ... ON DUPLICATE KEY UPDATE时,如果发生唯一键冲突,它会加X型的Next-Key Lock,在RC级别下同样可能引发死锁。
  • REPLACE INTO的行为更激进:它会在冲突记录以及它的下一条记录上都加上Next-Key Lock。
  • 即使没有显式地开启事务,单条INSERT语句本身也会开启一个隐式事务,锁要等到语句结束时才释放。
  • 如果一个没有索引的列被用来做唯一性判断?那情况会更糟,查询会退化为全表扫描并加上大量的记录锁,死锁风险反而可能更高。

RC 配置后为什么业务还出问题

配置了RC但业务依然出问题,最常见的原因其实是连接池或者ORM框架没有让配置真正生效。要知道,MySQL的默认隔离级别是RR,很多Ja va应用使用HikariCP配合MyBatis,连接从连接池取出后,其隔离级别可能依然沿用服务端的默认值,那条关键的SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED语句并没有被执行。

如何验证配置是否真的生效了呢?可以试试这几个方法:

  • 在连接建立后,立刻执行SELECT @@transaction_isolation进行查看。注意,要看的是会话级变量,而不是全局变量@@global.transaction_isolation
  • 检查慢查询日志,看看里面是否还有SELECT ... LOCK IN SHARE MODE这类语句。这类语句在RC下虽然不加Gap Lock,但如果没有显式地以BEGIN开启事务,它可能会按照会话的默认隔离级别(可能还是RR)来执行。
  • binlog格式必须设置为ROW,否则在RC级别下可能导致主从数据不一致。如果使用STATEMENT格式,RC下那些非确定性的语句将无法在从库正确重放。
  • Spring框架的@Transactional(isolation = Isolation.READ_COMMITTED)注解通常是有效的,但需要确认数据源本身的配置没有覆盖这个设置。

RC 不是银弹:哪些场景它反而更危险

必须清醒地认识到,RC并非万能解药,在某些场景下它反而会带来更大的风险。最典型的就是“先查询,后修改”这类业务逻辑。

以库存扣减为例:先执行SELECT stock FROM goods WHERE id = 123得到库存10,再执行UPDATE goods SET stock = 9 WHERE id = 123 AND stock >= 10。在RC级别下,这两个操作之间的时间窗口,其他事务可能已经把库存改成了9,最终导致超卖。

这时,你不得不借助SELECT ... FOR UPDATE来加锁。但问题在于,RC下的SELECT ... FOR UPDATE只锁行,不锁间隙。如果业务逻辑本身允许“幻读”(即允许在事务期间插入新记录),那没问题;但如果需要防止新记录的插入干扰判断(例如,防止在事务期间新增一个同规格的商品),RC就无能为力了。

还有一些容易被忽略的细节:

  • RC下,SELECT ... FOR UPDATE不会阻塞其他事务在相邻间隙中插入数据,所以如果业务需要“防止插入”,必须依靠应用层逻辑或数据库的唯一约束来兜底。
  • 长事务在RC级别下依然危险:虽然MVCC快照的维护开销较轻,但未提交的事务仍然会阻止purge线程清理undo log,长时间积累可能导致ibdata1文件膨胀。
  • 某些ORM框架自动生成的批量更新语句,即使在RC下,也可能因为where条件的顺序不一致,导致加锁顺序不同,从而引发死锁。

说到底,决定是否采用RC级别的关键,并不在于抽象的并发数字高低,而在于业务本身能否容忍不可重复读和幻读现象,以及开发团队是否有能力将核心的校验逻辑,收敛到单条具备原子性的SQL语句中去完成。

来源:https://www.php.cn/faq/2419345.html

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
Oracle 12c安装报OSDBA组不存在?预先创建用户组解决

Oracle 12c安装报OSDBA组不存在?预先创建用户组解决

在Linux上安装Oracle12c时,“OSDBAgroupdoesnotexist”报错因缺少dba组,需执行groupadddba并将用户加入该组,用id-a验证。Windows不识别dba组,应使用ORA_DBA组。config o文件硬编码OSDBA组名,需检查其值是否为dba。创建组后仍需注意sudo、su或容器等场景下会话上下文未继承新组的问题

时间:2026-07-06 07:07
高并发系统缓存更新先删缓存还是先更新数据库

高并发系统缓存更新先删缓存还是先更新数据库

高并发系统中缓存与数据库更新易致数据不一致。先删缓存再更新可能引入脏数据,建议先更新数据库再删缓存。延迟双删、MQ补偿及Canal监听binlog等方案可保证最终一致性,数据库是最终数据源,缓存为加速层。

时间:2026-07-06 07:07
SQL中DENSE_RANK为何比RANK更符合业务排名逻辑

SQL中DENSE_RANK为何比RANK更符合业务排名逻辑

在SQL中,RANK()函数因相同排名后跳号,导致TopN查询可能多出数据;而DENSE_RANK()不跳号,排名连续,更符合“第几档”业务语义,避免歧义,常应用于需要连续排名的分档统计场景中。

时间:2026-07-06 07:07
高并发SQL INSERT锁竞争成为系统瓶颈的原因

高并发SQL INSERT锁竞争成为系统瓶颈的原因

很多开发者想当然地认为INSERT只会锁定新插入的那一行,但实际情况远比这复杂。它不仅要施加行锁,还需要在检查唯一约束、分配自增ID以及维护二级索引时,额外申请insert intention lock、gap lock、next-key lock,甚至表级auto-inc lock。这些锁并非各自

时间:2026-07-06 07:07
如何在SQL SELECT语句中使用CASE WHEN函数实现复杂逻辑分支

如何在SQL SELECT语句中使用CASE WHEN函数实现复杂逻辑分支

CASEWHEN是表达式而非函数,若忘记ELSE或条件顺序写错易导致NULL结果。需注意数据类型隐式转换问题,在WHERE中宜用布尔表达式,ORDERBY中可自定义排序规则,聚合常与SUM COUNT函数搭配使用。避免深层嵌套,不同数据库语法有差异。

时间:2026-07-06 07:07
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 日榜
  • 周榜
  • 月榜