RC不加间隙锁,锁粒度更小:RR为防幻读在索引范围加Gap/Next-Key锁,RC仅对命中行加Record锁、不锁间隙,故并发更高、死锁更少。

RC不加间隙锁,锁粒度更小
RR隔离级别为防止幻读,会在WHERE条件涉及的索引范围上自动加Gap Lock或Next-Key Lock;而RC只对实际命中的记录加Record Lock,不锁间隙。这意味着:
- SELECT * FROM t WHERE id 在RR下会锁住(2,5)这个间隙,阻塞其他事务插入<code>id=4的行;
- 同样语句在RC下只锁id=1、id=2这两行,id=4可自由插入;
- 大量并发插入场景(如订单号自增、日志写入)下,RC的锁冲突明显减少。
RC支持半一致读,UPDATE时提前释放无关行锁
当执行UPDATE t SET status='done' WHERE status='pending'时:
- 在RR中,若status无索引,InnoDB会扫描全表并为**所有扫描过的行**加锁(即使最终不满足条件),导致整表被锁;
- 在RC中,MySQL Server层过滤不满足条件的行后,会调用unlock_row()主动释放这些行上的锁;
- 更关键的是,RC启用semi-consistent read:如果某行已被其他事务加锁,InnoDB返回其最近已提交版本供上层判断;若不满足WHERE条件,直接跳过、不等待——这大幅降低UPDATE语句的锁等待时间。
RC减少死锁概率,尤其在非主键更新场景
间隙锁是RR死锁高发的根源之一。例如两个事务分别执行:
- UPDATE t SET x=1 WHERE name LIKE 'a%'
- INSERT INTO t (name) VALUES ('ab')
在RR下,前者可能锁住('a', 'b')间隙,后者试图插入同一间隙,触发等待链;RC中无间隙锁,插入直接进行。
另外,RC下非主键条件更新只锁实际匹配行,而RR可能因全表扫描+间隙锁把整个聚簇索引“一锅端”,进一步放大死锁面。
RC的快照生成机制更轻量
RR的MVCC快照在事务内**第一次SELECT时生成**,后续所有读都基于该快照,但写操作仍需维护该快照与当前数据的映射关系; RC的快照是**每次SELECT时按需生成**,只依赖当前已提交版本,无需维护长事务快照链。 这对高吞吐写入场景很关键:长时间运行的只读事务在RR下会拖慢purge线程清理undo log,间接影响写性能;RC无此负担。
真正卡住性能的往往不是“要不要一致性”,而是“锁住多少、锁多久、谁在等谁”。RC把锁收缩到必要最小集,并让UPDATE具备“看一眼就走”的能力——这点在订单、库存、消息队列类业务里,比理论上的可重复读重要得多。



















