当前位置:网站首页>MVCC是什么
MVCC是什么
2022-08-04 23:36:00 【大佬,菜菜,带带】
什么是MVCC
MVCC是一种同一主键的行记录保存多个版本的机制,实现在并发读-写情况下不加锁读,同时解决了脏读、不可重复读。
MVCC如何实现
MVCC通过版本链实现。
什么是版本链
版本链就是一个链表,每个节点上保存的是行记录的一个版本,其中头节点是行记录的最新版本,头节点后的第一个节点是行记录最新版本的上一个版本,头节点后的第二个节点是行记录最新版本的上上一个版本,以此类推。
版本链如何实现
版本链又是如何实现的呢?其实InnoDB的行记录中除了我们自定义的列之外,还有三个隐藏列,分别是trx_id,roll_pointer,row_id:
trx_id:事务id,表示这条行记录是哪个事务生成/修改的
roll_pointer:指向undo log中这条行记录的上一个版本
row_id:当用户没有指定主键且没有非null的唯一列时,使用
row_id作为主键
通过roll_pointer就形成了版本链,有了版本链就可以查询到行记录的每个版本。
如何解决脏读、不可重复读问题
假如是我们来解决脏读和不可重复读问题,在有版本链的情况下应该如何解决呢?(一条行记录,创建/修改它的事务已经提交了,下面将简称已提交行记录,反之为未提交行记录)
脏读是指读到了未提交行记录,我们很容易想到:版本链上那么多版本,我们读一条已提交行记录不就行了?
不可重复读是指在一个事务中两次读取一个行记录,但是获取到的数据不一致,原因是在两次读取的间隔中有其他事务修改了这个行记录并提交了,那如果在当前事务提交之前无论读多少次都读取版本链上的同一个
已提交行记录,这样的话读到的数据不就一样了?那么哪个版本才能让我们在当前事务提交之前的各个时期都能读取到呢?那就是当前事务开始时的已提交行记录。至于当前事务开始时的未提交行记录甚至是当前事务开始之后才生成的未提交/已提交行记录都是不行的。
提炼一下解决脏读和不可重复读需要的条件:
解决脏读是需要读一个
已提交行记录;解决不可重复读是需要读取
当前事务开始之前的已提交行记录。
也就是说我们只要读取当前事务开始时的已提交行记录,并且当前事务没有提交之前每次都读同一个版本,那就可以解决脏读和不可重复读问题。
非礼勿视——ReadView
大概的思路就是这样,但是我们怎么知道我们读取的行记录是不是在当前事务开始时就已经提交了呢?这时候就轮到行记录隐藏字段trx_id上场了。
可能大家会想到,喔!我懂了!直接判断行记录的事务id和当前事务id的大小就行了,小于当前事务id的就是在当前事务开始时就已经提交的行记录;大于当前事务id的就是在当前事务开始之后才提交的行记录。
需要注意的是,事务id是事务对行记录创建/修改时分配的,而不是事务提交的时候分配的。一个事务的事务id小,但是因为操作比较多,可能比其他事务id大的事务提交的时间还要晚。所以只凭行记录事务id和当前事务id是无法判断生成这条行记录的事务是否是在当前事务之前提交的。
那么到底是如何实现判断的呢?InnoDB设计了一个ReadView,这个ReadView很简单,就4个部分,分别是:
m_ids:当前事务生成ReadView时活跃事务的列表(简称活跃列表)min_trx_id:活跃列表中最小的事务id(最小事务id)max_trx_id:生成ReadView时下一个要分配的事务id(最大事务id)creator_trx_id:生成ReadView的事务id(当前事务id)
有了ReadView我们就可以知道我们读取的这个行记录是不是在当前事务开始时就已经提交了:
首先这个版本的行记录事务id一定不能大于或者等于最大事务id,如果不满足,说明生成这个行记录的事务是在当前事务开始之后才生成的,肯定不行。
如果这个版本的行记录事务id比最小事务id要小,说明在当前事务生成时它已经提交了,可以读。
如果这个版本的行记录事务id和当前事务id一样,说明这个记录是当前事务修改/生成的,可以读。
如果这个版本的事务id比最小事务id要大,但是又比最大事务id要小,那就难办了,我们得看它是否在活跃事务列表中:
如果在,那说明这个行记录在当前事务开始时还没有提交,不行;
如果不在,那说明这个行记录在当前事务开始时提交了,可以读。
为什么需要活跃列表:一些事务的事务id比最小事务id要大,但是它可能在当前事务开始之前就已经提交了。
边栏推荐
猜你喜欢

隐私计算综述

【内存操作函数内功修炼】memcpy + memmove + memcmp + memset(四)

基于内容的图像检索系统设计与实现--颜色信息--纹理信息--形状信息--PHASH--SHFT特征点的综合检测项目,包含简易版与完整版的源码及数据!

Xiaohei leetcode surfing: 94. Inorder traversal of binary tree

360市值四年蒸发3900亿,政企安全能救命吗?

深度|医疗行业勒索病毒防治解决方案

uniapp sharing function - share to friends group chat circle of friends effect (sorting)

【字符串函数内功修炼】strcpy + strcat + strcmp(一)

建模师经验分享:模型学习方法

三大技巧让你成功入门3D建模,零基础小白必看
随机推荐
Linear DP (bottom)
测试技术:关于上下文驱动测试的总结
KT148A电子语音芯片ic方案适用的场景以及常见产品类型
The Controller layer code is written like this, concise and elegant!
OpenCV:10特征检测
@Async注解的作用以及如何实现异步监听机制
Laravel 实现redis分布式锁
隐私计算综述
Shell expect 实战案例
Service Mesh landing path
学会反射后,我被录取了(干货)
如何根据地址获取函数名
Will we still need browsers in the future?(feat. Maple words Maple language)
TypeScript - the use of closure functions
【手撕AHB-APB Bridge】~ AMBA总线 之 AHB
2022年华数杯数学建模
I was rejected by the leader for a salary increase, and my anger rose by 9.5K after switching jobs. This is my mental journey
truffle
App测试和Web测试的区别
一点点读懂regulator(二)