MySQL-多版本并发控制MVCC

文章目录


一、多版本并发控制MVCC

MVCC是多版本并发控制(Multi-Version Concurrency Control),是MySQL中基于乐观锁理论实现隔离级别的方式,用于实现已提交读和可重复读隔离级别的实现,也经常称为多版本数据库。MVCC机制会生成一个数据请求时间点的一致性数据快照 (Snapshot), 并用这个快照来提供一定级别 (语句级或事务级) 的一致性读取。从用户的角度来看,好象是数据库可以提供同一数据的多个版本(系统版本号和事务版本号)。事务的隔离性就是锁机制加MVCC 体现的。

MVCC多版本并发控制中,读操作可以分为两类:

1、快照读 (snapshot read)

读的是记录的数据快照,可以理解给数据拍了一张照片,不用加锁。如select

2、当前读 (current read)

读取的是当前事务记录的最新数据库版本,并且返回第一次select数据快照的记录。如insert,delete,update,select...lock in share mode/for update

已提交读和可重复读的底层实现原理 :通过MVCC多版本并发控制实现并发读取方式:快照读 。InnoDB提供了两个读取操作:锁定读非锁定读 。锁定读相关内容在锁机制里有提到,间隙锁排它锁与共享锁等;非锁定读就是MVCC提供的快照读,它实现依赖于依赖底层的一个技术,undolog回滚日志;
undolog回滚日志的主要作用:事务发生错误时回滚rollback,提供MVCC的非锁定读(快照读),查快照上的数据而不是最新的数据;

二、undo log(回滚日志)

undo log:回滚日志,保存了事务发生之前的数据的一个版本,用于事务执行时的回滚操作,也就是rollback操作;同时也是实现多版本并发控制(MVCC)下读操作的关键技术,提供MVCC的非锁定读(快照读)。

实现回滚日志的两个关键:DB_TRX_ID:事务IDDB_ROLL_PTR:回滚指针

通过上面的图片可以了解到,每一行记录实际上有多个版本 ,每个版本的记录除了数据本身之外,增加了其它字段 ;在记录行中隐式的记录了事务ID和回滚指针 ,这些隐式数据是给MySQL看的:

1、开启事务时,MySQL会给事务分配事务ID,同一个事务的事务ID是不变的,不同的事务ID不同;

2、事务修改后的数据,放在表中原来的位置上,修改之前的数据会被放置在undo log中(缓存中);旧数据与新数据通过回滚指针链接,类似链表的结构,通过链表就可以找到之前的旧数据,实现回滚操作;

二、已提交读

已提交读:可以解决事务并行的脏读问题,但是不能解决不可重复读和幻读问题。

sql 复制代码
//设置事务的隔离级别为 已提交读
set tx_isolation='READ_COMMITTED';

1、已提交读如何解决脏读问题?

每次select都会产生一次新的数据快照,前提是数据被事务成功commit过了,在数据没有被commit之前,每次读的数据都是第一次select的结果;当事务成功commit之后,select产生最新的数据快照,此时会发生不可重复读、幻读
2、为什么已提交读无法解决不可重复读、幻读?

因为每次select都会产生一次新的数据快照,其它事务更新以后成功commit,会导致当前事务再select的时候产生了数据更新后的数据快照,从而发生不可重复读和幻读。

三、可重复读

可重复读:可以解决事务并发产生的脏读、不可重复读问题;一定程度上解决幻读问题。

sql 复制代码
//设置事务的隔离级别为 可重复读
set tx_isolation='REPEATABLE-READ';

1、如何解决脏读问题?

也是通过数据快照解决的脏读问题;
2、如何解决不可重复读?

可重复读 隔离级别下,数据快照只在第一次select时候产生,不会因为其它事务成功commit就改变当前的数据快照。当前事务再次select时,仍然查看的是第一次select的数据快照。

3、为什么能部分解决幻读 问题?

但是在事务执行update时,进行当前读,会读取到其它事务成功commit的数据;此时当前的事务发生更新,再执行select时,会将修改后的数据也显示出来,显示的结果就是第一次select的数据快照和修改后的数据


总结

由于MVCC,所以每一行记录实际上有多个版本,快照内容读取原则:

1、版本未提交无法读取生成快照 ;

2、版本已提交,但是在快照创建后提交的,无法读取 ;

3、版本已提交,但是在快照创建前提交的,可以读取 。所以在已提交读隔离级别下会产生不可重复读;

4、当前事务内自己的更新,可以读到 。所以在可重复读隔离级别下会产生幻读。

相关推荐
黄林晴几秒前
Android17 为什么重写 MessageQueue
android
阿巴斯甜21 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker21 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95271 天前
Andorid Google 登录接入文档
android
黄林晴1 天前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab2 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿2 天前
Android MediaPlayer 笔记
android
Jony_2 天前
Android 启动优化方案
android
阿巴斯甜2 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇2 天前
AOSP15 Input专题InputReader源码分析
android