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
一致性 语句级一致性(每次读独立) 事务级一致性(全程一致)
适用场景 对一致性要求低、追求高并发的业务(如电商商品列表) 对一致性要求高的业务(如金融转账、订单支付)
相关推荐
a7963lin几秒前
html标签怎样表示搜索框_input type=search语义优化【操作】
jvm·数据库·python
a7963lin4 分钟前
Python数据分析如何识别异常值_IQR四分位距检测法实战
jvm·数据库·python
m0_613856296 分钟前
如何解决宝塔面板Web端文件管理器打开目录时反应极其缓慢
jvm·数据库·python
阿丰资源13 分钟前
基于Spring Boot的新闻推荐系统(源码+数据库+文档)
数据库·spring boot·后端
m0_6138562919 分钟前
mysql如何优化重复索引_mysql冗余索引查找与处理
jvm·数据库·python
四维迁跃20 分钟前
Python Web开发如何防范SQL注入_使用参数化查询与ORM实践
jvm·数据库·python
2401_8330336227 分钟前
如何自动更新SQL标签状态_利用触发器实现基于逻辑的状态机
jvm·数据库·python
2401_8314194431 分钟前
mysql如何优化数据库文件写入速度_配置innodb刷盘策略
jvm·数据库·python
YaBingSec41 分钟前
玄机网络安全靶场:Hadoop YARN ResourceManager 未授权 RCE WP
大数据·数据库·hadoop·redis·笔记·分布式·web安全
m0_6356474841 分钟前
Qt打包含有第三方库的软件为应用程序——CQtDeployer
开发语言·数据库·qt