RR级别为什么不能完全解决幻读案例分析 | 什么是MCVV

0. 知识前要:

  • 要分析这个问题,首先得清楚什么是MVCC,详细的可以查看看一遍就理解:MVCC原理详解
  • 这里小结一下:
    • MVCC 是多版本并发控制,主要实现读写冲突不阻塞,这个读指的是快照读
    • 它的实现主要依赖三个隐式字段、undo 日志、Read View
    • 每行记录除了自定义的字段外,还有隐式主键、事务 id、指向 undo 日志的指针
    • undo 日志记录有原始数据和修改数据,是个记录链,链首是最新的修改
    • Read View 是一致性读视图,用来判断记录的某个版本是否对当前事务可见
      • m_ids:当前系统中那些活跃(未提交)的读写事务ID列表
      • min_limit_id:最小的事务id
      • max_limit_id:最大的事务id,即分配给下一个事务的id值
      • creator_trx_id:当前的事务id
      • 匹配规则如下:
        在这里插入图片描述
    • RR 级别都是复用同一个 Read View,RC 则是每次快照读生成一个

1. 举个栗子:

  • 初始数据:
  • 在这里插入图片描述
1.1. 栗子一:两次快照读之间存在更新语句,更新其他事务已经更新过的数据
  • 事务B的更新语句提交之后,事务A对事务B已提交的数据再进行更新,则事务B已提交的数据对事务A是可见的
  • 官方文档也是这么介绍的,innodb-consistent-read,但文档也没找到原因
    ·在这里插入图片描述

在这里插入图片描述

  • 本栗子事务A最后的查询语句结果mobile=‘BBB’,amount=2000
1.1.1. 执行过程分析:
  • 存储引擎执行update语句的过程
    • 先从缓存池Buffer Pool读取数据,没有数据则从磁盘文件加载到缓存池
    • 更新时再缓存池修改,并将更新的数据记录到redo日志缓存池
    • 事务提交时,redo日志缓冲池根据策略写入redo日志磁盘文件,还会将本次修改的数据写入binlog,最后给redo日志追加commit标记
      ·在这里插入图片描述
  • 事务A执行update语句时,事务B已经提交,意味着更新时会先获取最新的数据(不管是缓缓存池还是数据库加载的)
1.1.2. MVCC分析:

在这里插入图片描述

  • 事务A第一次查询生成的视图快照,按照Read View的可见性判断规则,对比Undo版本链的记录
    • 对比版本链最新的数据
      • min_limit_id =<trx_id(100)< max_limit_id
      • m_ids包含版本记录的trx_id(100),且trx_id(100) = creator_trx_id
      • 所以第二次查询语句查询到的就是mobile=‘BBB’,amount=2000的数据
1.2. 栗子二:两次快照读之间存在更新语句,更新其他事务insert的数据

在这里插入图片描述

  • 事务A更新的数据是事务B新插入的数据,存在数据冲突
  • 和上述栗子一一样,此时事务B新插入的数据对事务A是可见的
  • 更新的时候会去取最新的数据取更新
  • 所以最终查询结果会看到id = 2,4 的数据,并且id=4 的amout = 2000;
1.3. 栗子三:两次快照读之间存在更新语句,要更新的数据不冲突

在这里插入图片描述

  • 和上面栗子一类似,只不过事务A更新的是id=5的数据
    • 事务B更新提交id=1的数据,事务A再更新id=5的数据,更新的数据与事务B提交的不冲突
    • 所以事务B提交的数据对事务A是不可见的
    • 最后的查询结果还是mobie = ‘AAA’,amount = 1000
1.4. 栗子四:使用锁定读取

在这里插入图片描述

  • 事务A第二条查询语句结果:mobie = ‘BBB’,amount = 1000
  • 事务A第二条查询语句使用FOR UPDATE 、FOR SHARE( LOCK IN SHARE MODE) 这类锁定读取(也属于当前读)
  • 从结果层面来看,猜测这类锁定读取不会使用版本链记录取匹配,而是直接获取的最新数据

3. 小结:

  • RR 级别通过 MVCC 保证快照读不会出现幻读,通过临建锁保证当前读不会出现幻读;
  • 但不能保证先快照读,再当前读的情况,所以严格意义上不算完全解决幻读
    • 如果两次查询之间出现Update、Delete语句这类当前读,并且操作的语句数据与别的事务提交的数据冲突,则DML对当前事务可见
    • 如果是锁定读取,会直接读取最新数据
  • 16
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值