Mysql如何实现原子性(MVCC实现原理)
Mysql实现原子性主要通过一下机制
- 锁
- MVCC多版本并发控制
MVCC的实现原理
在介绍MVCC的实现原理之前需要先介绍一下Mysql表中的隐藏字段 , 以及undo_log版本链以及readview
1. Mysql中的隐藏字段
Mysql在创建表的时候除了我们所定义的字段还定义了一下三个字段
- DB_TEX_ID --> 同来记录当前事务ID , 该字段是一个自增的Int , 每当事务开启后 , 就会对该ID自增
- DB_ROLL_TRX --> 该字段是记录上一个undo_log日志的地址
- DB_ROW_ID --> 当用户未指定主键时 , 该字段会作为主键
2. 什么是undo_log版本链
在事务执行增删改之前 , 会在undo_log日志当中记录当前的数据信息 , 并保存DB_TROLL_TAX记录上一个undo_log日志地址
如下图所示 , 我们开启了四个事务 , 对于每个事务的版本号为2 , 3 , 4 ,5
那么在事务的创建过程中就会在undo_log日志当中注册版本信息 , 如下图
那么当上述的事务都注册完毕就会形成一个版本链
3. 什么是readview
readview就是通过一定的机制来判断 , 当前版本的事务是否可以被读取 , 也就是说是快照读 sql执行的依据
当前读:
当前读就是记录最新版本的数据 , 在读取过程中会加锁
快照读
就是简单的select语句 , 在读取过程中不加锁 是非阻塞的 , 读取的数据有可能是当前数据 ,也有可能是历史数据
而对于快照读所读取的数据是什么也就是通过readview一下几点来实现的
首先在readview中保存了下列字段 , 分别用来记录当前并发日志的信息 , 通过该消息与一定的规则来实现快照读
规则如下
4. MVCC是如何基于readview, undo_log版本链与隐藏字段实现快照读
还是针对下述事务 , 我们来判断一下事务无的;i两次快照读分别命中了那个版本的数据
首先我们来分析第一次查询
m_ids: { 3 , 4 , 5}
min_trx_id: 3
max_trx_id : 6
creator_trx_id : 5
分析完readview后我们就要从undo_log版本链进行比对
可以看出来对于第一个查询命中的事务2 , 对于第二个查询命中的是事务3
介绍完隐藏字段 , undo_log日志链与readview这三个概念后, 对于MVCC要做什么怎么做应该有了一个大致的了解
MVCC多版本并发控制也就是在多个事务并发的情况下 , 通过readview判断快照读命中的是哪个语句 , 进而获取查询信息
=============================================================
面试官:事务中的隔离性是如何保证的呢?(你解释一下MVCC)
候选人:事务的隔离性是由锁和mvcc实现的。
其中mvcc的意思是多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,它的底层实现主要是分为了三个部分,第一个是隐藏字段,第二个是undo log日志,第三个是readView读视图
隐藏字段是指:在mysql中给每个表都设置了隐藏字段,有一个是trx_id(事务id),记录每一次操作的事务id,是自增的;另一个字段是roll_pointer(回滚指针),指向上一个版本的事务版本记录地址
undo log主要的作用是记录回滚日志,存储老版本数据,在内部会形成一个版本链,在多个事务并行操作某一行记录,记录不同事务修改数据的版本,通过roll_pointer指针形成一个链表
readView解决的是一个事务查询选择版本的问题,在内部定义了一些匹配规则和当前的一些事务id判断该访问那个版本的数据,不同的隔离级别快照读是不一样的,最终的访问的结果不一样。如果是rc隔离级别,每一次执行快照读时生成ReadView,如果是rr隔离级别仅在事务中第一次执行快照读时生成ReadView,后续复用
标签:事务,快照,log,实现,Mysql,undo,readview,版本,MVCC From: https://blog.csdn.net/xiugtt6141121/article/details/144211185