MySQL中RC和RR隔离级别的Read View实现有何差异

风杰酱_3098

风杰酱_3098

2026-10-24

552人浏览

原创

rc每次select都新建readview,rr仅首次快照读时创建并复用,核心差异在生成时机与复用逻辑:rc实时感知已提交变更,rr冻结可见性边界,从而分别导致不可重复读与事务内读一致性。

mysql中rc和rr隔离级别的read view实现有何差异

RC每次SELECT都新建ReadView,RR只在首次快照读时创建

关键差异不在结构本身,而在生成时机和复用逻辑。RC下,innobase_get_read_view() 在每次普通 SELECT 执行前被调用,生成一个反映“此刻”活跃事务状态的新 ReadView;RR 下,该函数仅在事务内第一次快照读(如 SELECT、SELECT LOCK IN SHARE MODE)时触发,后续所有快照读都复用同一个实例。

这意味着:RC 能及时感知其他事务的提交,RR 则“冻结”了可见性边界。比如事务 B 提交后,RC 事务 A 下一次 SELECT 就能看到新值;而 RR 事务 A 若已执行过首次 SELECT,后续哪怕等十分钟,只要事务未结束,仍沿用旧 ReadView,看不到 B 的修改。

  • 显式 BEGIN 或 START TRANSACTION 不会触发 ReadView 创建
  • 事务中先 UPDATE 再 SELECT,RR 仍会在那个 SELECT 时才建 ReadView,不是在 UPDATE 时
  • 长事务不释放 ReadView,会阻塞 purge 线程清理 undo log,导致磁盘空间持续增长

ReadView字段含义一致,但m_ids集合内容随时间显著不同

ReadView 结构本身(含 m_ids、min_trx_id、max_trx_id、creator_trx_id)在 RC 和 RR 中完全相同,判断可见性的逻辑也一致:对版本链上每个记录的 trx_id,按规则比对是否落在 [min_trx_id, max_trx_id) 区间、是否在 m_ids 中等。

区别在于:m_ids 是生成时刻的“活跃事务 ID 快照”。RC 的 m_ids 每次都变小(因 B 已提交,不再活跃);RR 的 m_ids 自首次创建后就固定,哪怕其中某些事务早已提交,它也不会更新——这正是“不可重复读被避免”的底层原因。

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载
  • RR 的 m_ids 可能包含大量已提交但未被 purge 的事务 ID,造成误判为“不可见”
  • RC 的 m_ids 更紧凑,但高频重建带来轻微 CPU 开销,在高并发短查询场景下可测出差异
  • max_trx_id 始终是“下一个将分配的事务 ID”,与隔离级别无关,只取决于系统全局计数器

Binlog格式限制RC在STATEMENT模式下不可用

当 binlog_format = 'STATEMENT' 时,MySQL 明确禁止将事务隔离级别设为 READ COMMITTED,否则执行任何写操作都会报错:ERROR 1598 (HY000): Binary logging not possible. Message: Transaction level 'READ-COMMITTED' in InnoDB is not safe for binlog mode 'STATEMENT'。

根本原因是:STATEMENT 格式依赖 SQL 语句重放,而 RC 下同一事务内多次 SELECT 可能返回不同结果,导致主从执行同一条 UPDATE 时依据的读取条件不一致,引发数据偏差。RR 因复用 ReadView,保证了语句级读一致性,所以兼容 STATEMENT。

  • 若必须用 RC,binlog_format 应设为 ROW 或 MIXED
  • MySQL 5.7+ 默认 binlog_format = 'ROW',此限制影响变小,但线上仍需确认配置
  • 该限制与 ReadView 实现无直接关系,但它是 RC 在生产环境落地时绕不开的约束

快照读与当前读混用时,ReadView不生效

ReadView 只控制快照读(普通 SELECT),对当前读(SELECT ... FOR UPDATE、UPDATE、DELETE)完全无效。后者总是读取最新已提交版本,并加锁。

典型误区:在 RR 事务中先 UPDATE(当前读,看到最新值并加锁),再 SELECT(快照读,却仍用旧 ReadView,可能读不到刚改的值)。这不是 bug,而是机制设计——ReadView 不负责“让读看到自己刚写的”,它只回答“哪些其他事务的修改对我可见”。

  • 想在事务内立即看到自己写的变更,后续 SELECT 必须显式加上 FOR UPDATE 或 LOCK IN SHARE MODE
  • RR 下 SELECT ... FOR UPDATE 仍可能触发 gap lock,而 RC 下通常只锁匹配行,不锁间隙
  • 不要指望 ReadView 解决“事务内读己写”问题,那是存储引擎层缓存或应用层逻辑该管的事
最易被忽略的一点:ReadView 生效的前提是“事务已开启且尚未执行过首次快照读”。如果事务里全是当前读(比如只做 UPDATE + COMMIT),那整个生命周期可能压根没生成过 ReadView —— 它不是事务的标配组件,而是快照读的按需产物。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

mysql

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4523

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

931

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1189

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

6481

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

3263

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

6440

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

8821

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1190

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1052

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL vs MySQL
PostgreSQL vs MySQL

共1课时 | 190人学习