1. MVCC的基本概念
1.1类数据库并发方案
读取-读取:没有问题,也不需要同时控制
读-写:有线进程的安全问题可能会导致事务分离问题,可能会遇到污读、幻读和不可重复的读取
写入:可能存在有线流程安全问题、更新丢失问题
什么是1.2mvcc
MVCC、全称多版本控制(multi-versionconcurrencycontrol )或多版本并发控制是乐观锁定的一种实现方式,可以实现无读写冲突、解决读写冲突的无锁定并发控制
注意:
MVCC仅在两个隔离级别上运行:读命令和读命令。
1.3快照引线和当前引线的解释
快照读取:
简单的select操作不需要上锁,基于MVCC和undo log来实现,读取记录的可视版本(可能是历史版本)。
当前加载:
特殊读取操作必须锁定,这是一种悲观锁定,它读取记录的最新版本,并锁定当前读取并返回的记录,以防止其他事务同时修改此记录。
插入/更新/删除
select .for update
select . lock in share mode
2. MVCC的基础实现
MVCC的目的是多版本并发控制,在数据库中的实现是为了解决读写的冲突,其实现原理主要依靠记录中的3个隐含字段,undo log,Read View来实现。
InnoDB MVCC的实现基于还原日志,通过回滚指针来构建所需的版本记录。 确定ReadView将显示哪些版本的数据。 Purge线程还会在ReadView中清理旧版本的数据。
2 .一个隐式字段
DB_TRX_ID
6byte,最近更改事务ID (更改/插入) :创建记录/上次修改记录的事务ID
DB_ROLL_PTR
与7byte、undo log一起使用的回滚指针,用于指向此记录的上一个版本
DB_ROW_ID
6如果6byte、隐式自增量ID (隐藏主键)或数据表中没有主键,InnoDB会自动使用DB_ROW_ID生成聚簇索引
注意:
实际上,每个记录的标头信息(record header )都有一个特殊的位(deletedflag ),用于指示当前记录是否已被删除
2.2还原日志
2.2.1基本概念
还原日志主要记录数据的逻辑变化,要在发生错误时回滚上一个操作,必须记录所有上一个操作,然后才能在发生错误时回滚。
角色:
回滚事务处理
还原日志用于保留数据更改前的值。 如果此更改出现异常,可以使用还原日志执行回滚操作以确保事务完整性。
还原日志只是在逻辑上将数据库恢复到其原始状态,在回滚时实际上执行的是相反的任务
MVCC用
还原日志的类型主要包括:
插入还原日志
更新还原日志
2.2.2插入还原日志
插入还原日志是由插入操作生成的还原日志。 因为insert操作的记录只显示在事务本身中,而不显示在其他事务中。 因此,可以在提交事务后直接删除此还原日志,而不需要purge操作。
2.2.3更新还原日志
update undo log记录为delete和update操作生成的undo log。 由于此还原日志必须提供MVCC机制,因此如果事务不再可提交,请将其删除。 在提交时放入还原日志链表,等待purge线程进行最后的删除。
具体工作原理应分以下情况进行研究
2.2.3.1更新主键
集群索引和辅助索引都不能进行in place update。 将生成这两个版本
update分两个阶段运行,首先删除该行,然后插入所需的行
2.2.3.2更新非主键
聚簇索引可以输入放置更新,辅助索引生成两个版本
聚集索引记录还原日志,而辅助索引不记录还原日志
必须更新二级索引,才能确定是否要更改索引页的MAX_TRX_ID
2.2.3.3删除操作
删除操作实际上并不直接删除,只是标记为删除,最后的删除操作由purge线程完成
2.2.4 purge线程的主要作用有以下两个:
清除还原日志
清除page中具有Delete_Bit标志的数据行。 在InnoDB中是指
务中的Delete操作实际上并不是真正的删除掉数据行,而是一种Delete Mark操作,在记录上标识删除,真正的删除工作需要后台purge线程去完成。2.3 Read View(读视图)
2.3.1 什么是Read View
Read View就是事务进行快照读操作的时候生产的读视图(Read View),在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的ID(当每个事务开启时,都会被分配一个ID, 这个ID是递增的,所以最新的事务,ID值越大)
2.3.2 作用
Read View主要是用来做可见性判断的, 即当我们某个事务执行快照读的时候,对该记录创建一个Read View读视图,把它用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的undo log里面的某个版本的数据。
2.3.3 核心算法(可见性算法)
Read View的三个属性trx_ids
一个数值列表,用来维护Read View生成时刻系统正活跃的事务ID
up_limit_id
记录trx_ids列表中事务ID最小的ID
low_limit_id
ReadView生成时刻系统尚未分配的下一个事务ID,也就是目前已出现过的事务ID的最大值+1
可见性判断的流程
遍历DB_TRX_ID执行以下步骤,直到找到当前事务可见的最新数据:
遍历方法:如果当前DB_TRX_ID这条记录不满足当前事务的可见性,可通过这条记录的DB_ROLL_PTR回滚指针去取出undo log中前一个版本的DB_TRX_ID
step1:比较DB_TRX_ID 小于 up_limit_id
如果小于,则当前事务能看到DB_TRX_ID 所在的记录;即该记录是可见的最新的记录
如果大于等于进入step2
step2:判断 DB_TRX_ID 大于等于 low_limit_id
如果大于等于则代表DB_TRX_ID 所在的记录在Read View生成后才出现的,那对当前事务肯定不可见,继续遍历下一个DB_TRX_ID
如果小于则进入step3
step3:判断DB_TRX_ID 是否在活跃事务之中
如果在,则代表当前事务的Read View生成时刻,DB_TRX_ID这个事务还在活跃,还没有Commit,DB_TRX_ID这个事务修改的数据,当前事务也是看不见的;即对当前事务不可见,继续遍历下一个DB_TRX_ID
如果不在,则说明,DB_TRX_ID这个事务在当前事务的Read View生成之前就已经Commit了,DB_TRX_ID这个事务修改的结果,对于当前事务是可见的
3. MVCC的工作原理
3.1 MVCC查询的工作流程
3.1.1 查询主键索引
生成Read View读视图
通过主键查找记录,根据记录里的DB_TRX_ID与Read View读视图进行可见性判断
配合DB_ROLL_PTR回滚指针和undo log来找到当前事务可见的数据记录
3.1.2 查询二级索引
生成Read View读视图
比较读视图的up_limit_id与MAX_TRX_ID大小
如果MAX_TRX_ID 小于本次Read View的up_limit_id,则全部可见,过滤记录中的有效记录
否则,无法通过二级索引判断可见性,需要一次遍历每条记录,反查到聚簇索引记录,通过聚簇索引记录来判断可见性
3.2 MVCC与隔离级别
MVCC 只在 Read Commited 和 Repeatable Read两种隔离级别下工作。在RC隔离级别下,是每个快照读都会生成并获取最新的Read View;
这就是我们在RC级别下的事务中可以看到别的事务提交的更新的原因在RR隔离级别下,则是同一个事务中的第一个快照读才会创建Read View, 之后的快照读获取的都是同一个Read View。
即RR级别下,快照读生成Read View时,Read View会记录此时所有其他活动事务的快照,这些事务的修改对于当前事务都是不可见的。而早于Read View创建的事务所做的修改均是可见
4. 参考
https://www.cnblogs.com/AlmostWasteTime/p/11466520.html
https://www.jianshu.com/p/8845ddca3b23
https://www.zhihu.com/question/27674363/answer/38034982
https://www.cnblogs.com/f-ck-need-u/archive/2018/05/08/9010872.html
https://www.cnblogs.com/xibuhaohao/p/11947041.html
https://blog.csdn.net/qiuyepiaoling/article/details/8054346
https://blog.csdn.net/shaochenshuo/article/details/76137652
https://www.cnblogs.com/stevenczp/p/8018986.html
https://www.cnblogs.com/rongdi/p/13378892.html
https://www.jianshu.com/p/336e4995b9b8
http://mysql.taobao.org/monthly/2015/04/01/
https://www.pianshen.com/article/50271826706/#Innodb__2
http://mysql.taobao.org/monthly/2018/11/04/
https://www.jianshu.com/p/8845ddca3b23
https://www.cnblogs.com/micrari/p/8144339.html更多的干货好文,欢迎关注公众号:小青菜的技术博客