Mysql-InnoDB-MVCC

MVCC详解

前言

2020.3.8
网上看到了很多关于MVCC的解析,结合《MySQL技术内幕》终于对其有了一定的理解。这里只是简单的把自己的想法update一下,希望在面试的时候能流畅地说出自己的理解。关于细节没弄明白的日后再分析。

MVCC是啥?

MVCC,多版本并发控制,是InnoDB实现的一种一致性非锁定读的方法。其存在的意义在于可以不用对该行获取锁,直接通过读取该行以前版本的快照,来实现一致性读。

以前的数据库中,需要读一行记录,如果该行正在写,则需要等待该行的X锁被释放了,才能对他进行读。MVCC的引入就是为了让读操作变得更快,不需要获取锁就可以进行读。

InnoDB中MVCC是怎么实现的?

主要是通过undo log来进行实现的。当需要读取某行的时候,会通过undo log回滚到一个合适的版本作为一个快照,读取该快照作为最终的结果。该快照不需要进行上锁,因为没有事务会去修改一个以前的版本。

不同的隔离策略对应的不同的回滚的版本,MVCC只支持Read Commited和Repeatable Read

  • Read Commited:回退到当前锁定行最新的一份快照数据
  • Repeatable Read:回退到当前事务开始的行数据版本

为什么不同的策略会有不同的效果?

这就需要对MVCC底层实现的机制进行分析:

首先,每一行数据除了储存对应的属性的信息之外,还会存储如下几个属性:

  • DB_TRX_ID:最近修改该数据行的事务号
  • DB_ROLL_PTR:该数据行的undo log的指针

一个简单的事务修改行数据的演示如下:
在这里插入图片描述
当行数据需要回滚的时候,只需要根据DB_ROLL_PTR不断的遍历到自己需要回滚的版本,然后得到那一条Undo log即可。那么为什么不同的策略会回滚到不同的版本呢?

ReadView

ReadView是一个数据结构,每个事务中记录一份,用于判断事务的可见性。我们可以把Read View简单的理解成有三个全局属性:

  • trx_list
    一个数值列表,用来维护Read View生成时刻系统正活跃的事务ID
  • up_limit_id
    记录trx_list列表中事务ID最小的ID,小于该值的事务都已经被提交了
  • low_limit_id
    ReadView生成时刻系统尚未分配的下一个事务ID,也就是目前已出现过的事务ID的最大值+1,大于该值的事务是在该ReadView生成之后才产生的
  1. 首先比较DB_TRX_ID < up_limit_id, 如果小于,则当前事务能看到DB_TRX_ID 所在的记录,如果大于等于进入下一个判断
  2. 接下来判断 DB_TRX_ID 大于等于 low_limit_id , 如果大于等于则代表DB_TRX_ID 所在的记录在Read View生成后才出现的,那对当前事务肯定不可见,如果小于则进入下一个判断
  3. 判断DB_TRX_ID 是否在活跃事务之中,trx_list.contains(DB_TRX_ID),如果在,则代表我Read View生成时刻,你这个事务还在活跃。

由此可见,ReadView生成的时机不同,则对于其他事务的可见性也不同,因此对于可以回滚到的版本也会产生差异。

  • Read Commited策略下,事务中每执行一次SELECT时候就会更新一遍ReadView
  • Repeatable Read策略下,只有第一次执行SELECT前才会初始化ReadView

快照读和当前读

快照读是值读取该行的某一个事务可见版本的快照(可能过期),不用加锁,当前读是指读取当前行最新的版本,需要加锁。

当前读的情况:

  • select … in share mode;
  • select … for update;
  • update
  • delete
  • insert

快照读:

一般的select操作都是快照读

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值