MySQL-MVCC
MVCC
以下针对的是InnoDB引擎
什么是可重复读
在可重复读的事务隔离级别下,当我们开启一个事务时,其他事务后续的改动,当前事务查询到的数据还是事务刚刚启动时候内容。这个实际上就是MySQL的MVCC做的事情。
1 | -- 事务1 |
那么,MySQL的MVCC是怎么做到这一切的呢?
实现MVCC依赖到了MySQL的一致性视图 consistent read view (支持RC 读提交和RR 可重复读)
关于这个一致性视图,它并不是我们之前使用到的查询时候建立的虚拟表(view),没有一个具体的物理结构,作用就是定义了事务执行时能看到什么样的数据。
然后,对于MySQL各个隔离级别使用这个一致性视图的情况如下:
- 读未提交:直接返回记录上的最新值,不存在视图的概念
- 读提交:一致性视图是在每个SQL语句开始执行的时候创建的
- 可重复读:事务启动的时候创建的,整个事务存在期间都是用同一个视图
- 串行化:直接加锁来避免并行访问
1 | -- 这里补充一个查询事务隔离级别的命令 |
可重复读历史数据版本实现原理
首先明确一点:关于这个历史数据,并不是在事务开启时对历史数据进行一个快照版本备份(数据量大,成本太高),而是通过事务id和undolog来实现的
关于事务id
InnoDB里面每一个事务都有一个唯一的事务id(transaction id),它是事务开启的时候向InnoDB的事务系统申请的,根据申请顺序严格递增的。
然后对于每次更新操作,数据库是这样记录的
V1,V2,V3实际上是不存在,而是根据V4和undolog逆推实时计算出来的
那么,关于可重复读,MySQL是如何知道要逆推到哪个版本就可以结束了呢?
InnoDB为每个事务构建了一个数组,用来保存事务启动瞬间,当前正在活跃(启动但还没有提交)的所有事务id。
关于当前事务可以看到的数据版本,有以下几种可能
- 如果trx_id落在绿色部分,说明是已经提交的事务或者是当前事务自己生成的,对当前事务是可见的
- 如果落在红色部分,说明是当前事务以后的事务生成的,不可见
- 如果落在黄色部分
- trx_id在数组中,说明这个版本的数据由未提交的事务生成,不可见
- trx_id不在数组中,说明这个版本的数据是已经提交的事务生成,可见
- Post title:MySQL-MVCC
- Post author:大黄
- Create time:2023-01-06 16:53:55
- Post link:https://huangbangjing.cn/2023/01/06/MySQL-MVCC/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.