RC和RR隔离级别下MVCC的差异?

读已提交(RC)和可重复读(RR)是 InnoDB 中基于 MVCC 实现的两个核心隔离级别,二者的核心差异在于 Read View 的生成时机,这直接导致了快照读的一致性、版本可见性判断的不同

我们从核心差异点、行为对比、实例验证三个维度拆解,结合之前的版本链、Read View 知识,帮你彻底理清。

一、核心差异:Read View 的生成时机

这是 RC 和 RR 隔离级别下 MVCC 行为差异的根源,没有之一。

隔离级别 Read View 生成时机 核心影响
读已提交(RC) 每次执行快照读(普通 SELECT)时,都生成一个新的 Read View 每次读都会基于最新的活跃事务列表判断版本可见性,能看到其他事务刚提交的版本
可重复读(RR) 事务中第一次执行快照读时生成 Read View,后续所有快照读复用这个 Read View 整个事务内用同一个判断规则,多次读同一数据结果一致,不会看到其他事务提交的版本

补充:当前读(SELECT ... FOR UPDATE/INSERT/UPDATE)在两个隔离级别下行为完全一致------ 都是读取最新版本并加锁,不依赖 Read View 快照。

二、关键行为差异对比

基于 Read View 生成时机的不同,RC 和 RR 在 MVCC 层面会表现出 3 个核心差异,这也是面试高频考点:

对比维度 读已提交(RC) 可重复读(RR)
快照一致性 不保证可重复读:同一事务内多次快照读同一数据,结果可能不同 保证可重复读:同一事务内多次快照读,结果完全一致
版本可见性 能看到其他事务在两次快照读之间提交的新版本 看不到其他事务在本事务执行期间提交的任何版本
幻读问题 存在幻读:两次 SELECT 可能返回不同数量的行 解决幻读:InnoDB 通过 Next-Key Lock (行锁 + 间隙锁)配合 MVCC,避免幻读
Undo Log 清理 清理更及时:因为每次读都用新 Read View,旧版本很快不再被引用 清理较慢:因为事务复用 Read View,旧版本可能被长时间引用

三、实例验证:同一个场景下 RC 和 RR 的不同表现

用一个经典并发场景,直观对比两者差异。前置条件

  • user 表 id=1 的数据版本链:当前版本(102:王五) → 历史版本1(101:李四) → 历史版本2(0:张三)
  • 事务 102 未提交时,开启事务 103 执行快照读。

场景流程

时间 事务 102(未提交) 事务 103(隔离级别 RC) 事务 103(隔离级别 RR)
T1 UPDATE user SET name='王五' WHERE id=1;(未提交) 开始事务 开始事务
T2 - SELECT name FROM user WHERE id=1;(快照读) SELECT name FROM user WHERE id=1;(快照读)
T3 提交事务 - -
T4 - SELECT name FROM user WHERE id=1;(快照读) SELECT name FROM user WHERE id=1;(快照读)

结果分析

  1. T2 时刻(事务 102 未提交)

    • 无论 RC/RR,生成的 Read View 中 m_ids 都包含 102(活跃事务)。
    • 判断当前版本(102: 王五):DB_TRX_ID=102m_ids 中 → 不可见。
    • 遍历版本链,找到历史版本 1(101: 李四):DB_TRX_ID=101 < min_trx_id → 可见。
    • RC/RR 结果一致 :返回 李四
  2. T4 时刻(事务 102 已提交)

    • RC 隔离级别 :第二次 SELECT生成新的 Read View ,此时 m_ids 已不包含 102(事务 102 已提交)。判断当前版本(102: 王五):DB_TRX_ID=102 不在 m_ids 中 → 可见。结果 :返回 王五(两次读结果不同,不保证可重复读)。
    • RR 隔离级别 :第二次 SELECT 复用 T2 生成的 Read Viewm_ids 仍包含 102。判断当前版本(102: 王五):DB_TRX_ID=102m_ids 中 → 不可见。继续遍历版本链,返回 李四(两次读结果相同,保证可重复读)。

四、总结:RC 和 RR 的 MVCC 差异本质

本质 读已提交(RC) 可重复读(RR)
核心区别 每次快照读刷新 Read View 事务内复用 Read View
一致性 语句级一致性(每次读独立) 事务级一致性(全程一致)
适用场景 对一致性要求低、追求高并发的业务(如电商商品列表) 对一致性要求高的业务(如金融转账、订单支付)
相关推荐
北顾笙9805 小时前
MYSQL-day03
数据库·sql·mysql
MXsoft6185 小时前
**混合云统一监控实践:私有云+公有云的一体化运维方案**
运维·网络·数据库
瀚高PG实验室5 小时前
java中间件无法连接数据库
java·数据库·中间件·瀚高数据库
ULIi096kr5 小时前
MySQL大表优化终极方案:单表数据量上限、卡顿解决、分表分库实战教程
数据库·mysql
霖霖总总5 小时前
[MongoDB小技巧07]MongoDB 深度解析:find中投影与排序的底层机制与性能调优实战
数据库·mongodb
TechWayfarer5 小时前
云服务器地域怎么选:用离线IP数据库识别用户来源并优化部署
服务器·数据库·python·tcp/ip·数据分析
deviant-ART5 小时前
MySQL里的三个concat函数
数据库·mysql
H_老邪5 小时前
1044 - Access denied for user ‘root‘@‘%‘ to database ‘nacos‘
数据库·mysql
数智化精益手记局6 小时前
拆解复杂项目管理流程:用项目管理流程解决跨部门协作低效难题
大数据·运维·数据库·人工智能·产品运营
xhtdj6 小时前
Uber 如何通过批处理实现单账户每秒30+次更新
大数据·数据库·人工智能·安全·动态规划