舷Kelvin 2023-03-17 01:53 采纳率: 61.5%
浏览 22

对MySql的RR隔离级别下MVCC机制有些疑惑

img


上图是一个演示RR隔离级别下MVCC的例子,基于这个例子有点扩展性的问题琢磨不清,特来球教一下大家:

就是图中事务5中的查找是基于id的,如果改成依照age=3来查找,会是什么情形?

当然第一次查询是能找到id=30的这条数据的,按照理想状况,第二次查询应该也能。
但是按照目前我对该机制的理解,逐个回溯历史版本的第一步是在数据库(当前最新状态)中找到对应的数据吧,此时id=30的这条数据已经被事务4改成age=10了,那查询的第一步就找不到这条数据了吧。同时也不会直接去undo log里找对应的历史数据吧,不沿着数据版本链找等于大海捞针。
那岂不是就会出现一个很反直觉的情形?——明明是RR隔离级别下的两次快照读,中间也没穿插当前读,用的ReadView都是同一个。但读到的数据已经不一样了,是不是属于直接违反可重复读的定义了?

然后我又想到一种可能,这种情形是不是属于幻读?但是就我之前学到的理论里,幻读包括的情形有“读取时不存在但试图插入数据时却提示数据已存在而插入失败”或者“查询时存在但试图删除或修改时却提示不存在”,都在试图进行DML操作时才暴露问题,但上面例子里明明是两个单纯的查询,特征上也不符合。是我用的教程太过狭隘么?还是刚刚的推断中有所偏差(压根不是幻读)?还是有啥我没有掌握或理解偏差的基础知识?实在有些迷惑,求各位指点一二,谢谢大家。

  • 写回答

3条回答 默认 最新

  • 追cium 2023-03-17 03:40
    关注

    参考GPT和自己的思路:

    首先,如果将查询条件从id改为age=3,那么在MVCC机制下的查询流程是类似的。事务5会创建一个ReadView,并读取ReadView创建时的最新快照数据。如果ReadView创建后事务4修改了数据,那么事务5在遍历数据历史版本时,会发现版本号为3的数据满足条件,因此会将其返回。这个过程中并不会涉及到undo log,因为读取操作不会对数据进行修改。

    然而,如果此时有其他事务对数据进行修改或插入操作,就有可能出现幻读的情况。幻读是指在一个事务读取数据时,由于其他事务插入或删除数据,导致事务执行的查询结果与之前不同。在RR隔离级别下,事务读取的数据是基于当前时间创建的快照,因此没有办法防止幻读。MySQL的InnoDB引擎使用Next-Key Locks来通过锁定索引范围来避免幻读。具体细节可以参考InnoDB的实现文档。

    评论

报告相同问题?

问题事件

  • 修改了问题 3月17日
  • 修改了问题 3月17日
  • 创建了问题 3月17日

悬赏问题

  • ¥15 YOLOv8已有一个初步的检测模型,想利用这个模型对新的图片进行自动标注,生成labellmg可以识别的数据,再手动修改。如何操作?
  • ¥30 NIRfast软件使用指导
  • ¥20 matlab仿真问题,求功率谱密度
  • ¥15 求micropython modbus-RTU 从机的代码或库?
  • ¥15 django5安装失败
  • ¥15 Java与Hbase相关问题
  • ¥15 后缀 crn 游戏文件提取资源
  • ¥20 bash代码推送不上去 git fetch origin master #失败了
  • ¥15 LOL外服加入了反作弊系统,现在游戏录像rofl文件离线都无法打开
  • ¥15 在centos7安装conda