关于InnoDB引擎在RR级别下解决幻读的原理困惑之处

Listening_倾听 2020-01-05 04:22:49
在高性能MySQL第三版一书中看到InnoDB通过MVCC解决了幻读的问题,大致原理就是每行存在两个隐藏列,创建版本号和删除版本号,每个事务开始时,都会获得一个系统版本号,系统版本号是递增的。

我们先假设用户表当前只存在一个用户,创建版本号为10


有A、B两个事务经过了如下操作


我们再看当前用户表数据


根据MVCC的规则,SELECT只会找出系统版本号小于等于当前事务版本的数据行,所以问题就来了,id为2的数据是在版本号为11的事务创建的,事务B的版本为12,在T6时刻的SELECT仍然只有一条数据,这确实是解决了幻读,但跟MVCC所说的解决原理不一样啊。

我查了很多解释InnoDB的MVCC的原理的帖子,都没有来解释这个问题,都只是说B事务插入的数据在A事务中找不到而已,而且还有另一个问题就是如果在T4时刻事务B没有进行SELECT操作,那么在T6时刻进行SELECT操作确实有两条数据。
...全文
179 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
wandier 2020-01-07
  • 打赏
  • 举报
回复
当执行select操作是innodb默认会执行快照读,会记录下这次select后的结果,之后select 的时候就会返回这次快照的数据,即使其他事务提交了不会影响当前select的数据,这就实现了可重复读了。
Listening_倾听 2020-01-05
  • 打赏
  • 举报
回复
简单了解了一下,这个或许得用ReadView来解释。 在RR隔离级别下,事务中的第一个SELECT语句开始时创建ReadView,ReadView有以下几个主要的属性: trx_list: Read View生成时刻系统中正活跃的事务列表,当前示例为 [11] up_limit_id: 记录trx_list列表中事务最小的id,当前示例为 11 low_limit_id: 记录下一个待分配的事务id,当前示例为 13 每一行都有一个db_trx_id,代表创建(修改)时的事务id 查找原则: up_limit_id > db_trx_id,则可见; low_limit_id <= db_trx_id,表示后面的事务的创建的,不可见; up_limit_id <= db_trx_id < low_limit_id,如果 db_trx_id 在 trx_list 中,则不可见,否则可见。 这种解释是否合理,可以解释得通上面两种情况出现的结果。

56,675

社区成员

发帖
与我相关
我的任务
社区描述
MySQL相关内容讨论专区
社区管理员
  • MySQL
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧