MySQL:基于undo log多版链条实现的ReadView机制,到底是什么

ReadView机制

这个ReadView机制,简单来说,就是执行一个事务的时候,会生成一个ReadView,里面比较关键的东西有四个:

  • 一个是m_ids,就是说此时有哪些事务在MySQL里执行还没提交的
  • 一个是min_trx_id,就是说m_ids里最小的值
  • 一个是max_trx_id,就是说MySQL下一个要生成的事务ID,就是最大事务ID
  • 一个是creator_trx_id,就是说当前事务的ID

举个例子

  • 假设原来数据库里就有一行数据,很早一起就有事务插入过了,事务的ID是32,它的值就是初始值,如下图所示:

在这里插入图片描述

  • 接着假设两个事务并发过来执行了,一个是事务A(id=45),一个是事务B(id=59),事务B是要去更新这行数据的,事务A是要去读取这行数据的值的。此时两个事务如下图所示:

在这里插入图片描述

  • 现在事务A直接开启一个ReadView,这个ReadView的m_ids就包含了事务A和事务B的两个ID,45和59,然后min_trx_id就是45,nax_trx_id就是64,creator_trx_id就是45,是事务A自己
  • 这个时候事务A第一次查询数据,会走一个判断,判断一下当前这个数据的txr_id是否小于ReadView中的max_trx_id。此时发现txr_id=32,是小于ReadView里的min_trx_id就是45的。说明事务A开启之前,修改这行数据的事务早就提交了,所以此时可以查到这个数据。如下图所示:
    在这里插入图片描述
  • 接着事务B开始动手了,他把这行数据的值修改为了值B,然后这行数据的txr_id设置为自己的id,也就是59,同时roll_pointer指向了修改之前生成的一个undo log,接着这个事务B就提交了,如下图所示:

在这里插入图片描述

  • 这个时候事务A再次查询,此时查询的时候,会发现一个问题,那就是此时数据行里的txr_id=59,那么这个txr_id是大于ReadView里的min_txr_id(45),同时小于ReadView里的max_trx_id(60)的,说明更新这条数据的事务,很可能就跟自己差不多同时开启的,于是会看一下这个txr_id=59,是否在ReadView的m_ids列表里?
  • 果然,在ReadView的m_ids列表里,有45和59两个事务ID,直接证实了,这个修改数据的事务是跟自己同一时段并发执行然后提交的,所以对这行数据时不能查询的!如下图:
    在这里插入图片描述
  • 那么既然这行数据不能查询,那查怎么呢?
    • 简单,顺着这条数据的roll_pointer顺着undo log日志链条往下找,就会找到最近的一条undo log,trx_id是32,此时发现trx_id=32,是小于ReadView里的min_trx_id(45)的,说明这个undo log版本必然是在事务A开启之前就执行且提交的。
    • 也就是说,查询最近的那个undo log里的值就好了,这就是undo log多版本链条的作用,可以保存一个快照链条,让你可以读到之前的快照值。如下图:

在这里插入图片描述

  • 从上面可以看出,多个事务并发执行的时候,事务B更新的值,通过这套ReadView+undo log日志链条的机制,就可以保证事务A不会读到并发执行的事务B更新的值,只会读到之前最早的值
  • 接着假设事务A自己更新了这行数据的值,改为值A,trx_id修改为45,同时保存之前事务B修改的值的快照。如下图所示:
    在这里插入图片描述
  • 此时事务A来查询这条数据的值,会发现这个trx_id=45,跟自己的ReadView里的create_trx_id(45)一样。这说明这行数据就是自己修改的!自己修改的值当然是可以看到的。如下图:

在这里插入图片描述

  • 接着事务A执行的过程中,突然开启了一个事务C,这个事务的id是78,然后它更新了那行数据的值为值C,还提交了。如下图:

在这里插入图片描述

  • 这个时候,事务A再去查询,会发现当前数据的trx_id=78,大于了自己的ReadView中的max_trx_id(60),此时说明了什么?
  • 说明是这个事务A开启了之后,然后有一个事务更新了数据,自己当然是不能看到的了!。如下图:

在这里插入图片描述

  • 此时就会顺着undo log多版本链条往下找,自然先找到值A自己之前修改的过的那个版本,因为那个trx_id=45跟自己的ReadView里的creator_trx_id是一样的,所以此时直接读取自己之前修改的那个版本,如下图。

在这里插入图片描述

总结

  • 通过undo log多版本链条,加上开启事务时产生的一个ReadView,然后再有一个查询的时候,根据ReadView进行判断的机制,你就会知道你应该读取哪个版本的数据
  • 而且它可以保证你只能读到你事务开启前,别的提交事务更新的值,还有就是你自己事务更新的值。
  • 假如你事务开启之前,就有别的事务在运行,然后你事务开启之后,别的事务更新了值,你是绝对读不到的。或者是你事务开启之后,比你晚的事务更新了值,你也是读不到的
  • 通过这套机制就可以实现多个事务并发执行时候的数据隔离
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值