mysql的mvcc 2021-03-22(未允禁转)

2021-03-22  本文已影响0人  9_SooHyun

1.mvcc概要

指Multi-Version Concurrency Control,多版本并发控制。

2.mvcc的具体实现

mvcc主要依赖隐藏字段,ReadView和undo log实现

2.1 隐藏字段

隐藏字段的主要功能是,记录最后一次修改数据的事务,并且可以追溯历史版本的数据

Internally, InnoDB adds three fields to each row stored in the database:

以上介绍来源于MySQL8.0 InnoDB Multi-Versioning
这说明,MySQL8.0里面对每行数据加入的隐藏字段有3个:

2.2 ReadView

2.2.1 ReadView基本概念

ReadView,读视图,决定了哪些版本的数据对事务可见。换句话说,事务是依据ReadView选择可见数据的,ReadView看得见什么,事务就看得见什么。ReadView是不同事务间实现多版本数据的根本,我们讨论哪些数据对特定事务可见,其实是在讨论哪些数据对特定的ReadView可见

2.2.2 ReadView的产生

注意:事务begin不生成ReadView,一个事务的ReadView在事务内【执行普通select】操作时生成。而且,只有普通select语句才会创建ReadView,select ... lock in share mode,select ... for update不会,update、delete、insert语句也不会,因为它们都是当前读,会对访问的数据加锁
以多事务的update为例:


其中,// number表示命令的执行顺序。可以看到,// 2的update给数据上锁之后,// 3就会一直等待

读提交和可重复读,实际上就是通过ReadView的不同机制实现的。

2.2.3 ReadView的数据结构

下面来看一下ReadView究竟长什么样

ReadView主要依赖以下几个字段:

ReadView的核心是trx_ids。

遍历所有record,记遍历到的当前record的DB_TRX_ID为t_id

    1. if t_id out of [up_limit_id, low_limit_id)
      要么是id < up_limit_id,即修改当前record的事务已经commit,显然已完成事务的数据更改是对rv可见的;
      要么是id >= low_limit_id,即在rv产生后才创建的事务,这些事务对record的修改在rv的未来发生,对rv不可见,那么就顺着record的DB_ROLL_PTR一直找到rv可见的历史版本数据
    1. else up_limit_id <= t_id < low_limit_id
      此时如果t_id in trx_ids,就表明最后修改该record的事务在rv创建时处于活跃状态中,也就是说t_id和T在rv创建时刻是并行活跃的,出于事务间的独立性,该record对rv不可见,那么就顺着record的DB_ROLL_PTR一直找到rv可见的历史版本数据
      否则,t_id not in trx_ids,说明在rv产生的时候,最后修改该record的事务早已经提交了,因此record对rv可见

2.3 Undo log

Undo log以链表形式存储了历史版本数据,如果当前记录行对事务不可见,需要顺着undo log链找到满足其可见性条件的记录行版本

3. 例子

基于ReadView的MySQL mvcc例子
本图例来自MySQL中MVCC的正确打开方式(源码佐证),本文整理的内容也参考了其中的内容。还是要多看官方文档,多看源码,比啥都强
上一篇 下一篇

猜你喜欢

热点阅读