Mysql MVCC

本文介绍了数据库的快照读与当前读(MVCC)机制,涉及事务链、undoLog、隐式字段和ReadView的概念,详细解释了事务ID如何决定数据可见性,以及ReadView的生成和校验规则。
摘要由CSDN通过智能技术生成

数据库的两种读,每种读读的数据版本不一样(快照读和当前读),所以也称为MVCC,即多版本并发控制

版本链

又称事务链,每次修改数据的时候,都会记录一条undoLog日志,日志中记录数据每一次的变化,并且通过数据中的两个隐藏列

db_trx_id(事务id) 用标记每一条数据对应的事务id。
db_roll_ptr(指针) 用来串联版本链的指针。

db_row_id:隐藏主键,如果我们没有给这个表创建主键,那么会以这个字段来创建聚簇索引。

因为每一次记录变更之前都会先存储一份快照到undo log中,那么这几个隐式字段也会跟着记录一起保存在undo log中,就这样,每一个快照中都有有一个db_trx_id字段记录了本次变更的事务ID,以及一个db_roll_ptr字段指向了上一个快照的地址。(db_trx_id和db_roll_ptr是重点,后面还会用到)

这样,就形成了一个快照链表:

在这里插入图片描述

有了undo log,又有了几个隐式字段,我们好像还是不知道具体应该读取哪个快照,那怎么办呢

这时候就需要Read View 登场了

ReadView

阅读视图,可以理解为某一次读取的时候,根据不同的事务生成的数据快照,并且除了表中的数据,还有一下这些固定字段。

  • trx_ids,系统当前未提交的事务 ID 的列表。

  • low_limit_id,应该分配给下一个事务的id 值。

  • up_limit_id,未提交的事务中最小的事务 ID。

  • creator_trx_id,创建这个 Read View 的事务 ID。

每开启一个事务,我们都会从数据库中获得一个事务 ID,这个事务 ID 是自增长的,通过 ID 大小,我们就可以判断事务的时间顺序。

那么,一个事务应该看到哪些快照,不应该看到哪些快照该如何判断呢? 关键点来了

其实原则比较简单,那就是事务ID大的事务应该能看到事务ID小的事务的变更结果,反之则不能!

假如当前有一个事务3想要对某条记录进行一次快照读的时候,他会先创建一个Read View,并且把当前所有还未提交的事务的信息记录下来。比如up_limit_id = 2,low_limit_id = 5,trx_ids= [2,4,5],creator_trx_id= 6(这里都是未提交的事务,牢记)
在这里插入图片描述

ReadView生成规则

  • READ COMMITTED(读已提交): 在一个事务中,每次查询都会生成一个新的ReadView

  • REPEATABLE READ(可重复读) :在一个事务中只会在第一次执行查询语句时生成一个ReadView,之后的查询就不会重复生成了

ReadView校验规则

  • db_trx_id:对这条记录做了最新一次修改的事务的ID
  • low_limit_id:应该分配给下一个事务的id 值。
  • up_limit_id:未提交的事务中最小的事务 ID。
  1. 如果db_trx_id与ReadView中的creator_trx_id值相同,说明当前事务修改的记录就是在当前事务下操作的,那当然是对我们可见的了,因此可以修改这条记录

  2. 如果db_trx_id小于ReadView中up_limit_id值,说明(生成该版本的事务在该事务生成readView之间已经提交)即当前事务在开启的时候,这条记录最近一次被其他事务操作的事务已经提交了,所以对这条记录对我们来说也是可以见,可以修改

  3. 如果db_trx_id大于或者等于ReadView中low_limit_id值,说明(生成该版本的事务在当前事务生成readView之后才开启)即:我们开启事务未修改该记录之前,已经有另外一个事务开启,并且正在修改该事务了,因此,这条记录对我们来说依然是不可见的,我们不能修改

  4. 如果db_trx_id介于ReadView中 up_limit_id 和 low_limit_id 之间的话
    有两种情况,分析当db_trx_id是否在 trx_ids 中

    ① 如果在,说明(创建ReadView时,生成该版本的事务还处于活跃状态)即:当前已经有其它的事务正在修改该条记录,并且还未提交,此时这条记录对我们不可见

    ② 如果不在,说明(创建ReadView时,生成该版本的事务已经提交)即:此时没有事务操作该条记录,我们可以修改该条记录

当数据的事务ID不符合Read View规则时候,也就是不可见的时候,那就需要从undo log里面通过版本链的回滚指针找到这条记录的上一个版本在进行判断,直到遍历版本链找到对当前查询可见的版本返回,找不到则返回空。

  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值