你解释一下MVCC?
mvcc的意思是多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,
它的底层实现主要是依赖了数据库中的三个部分,隐藏字段,undo log日志和readView读视图
隐藏字段是指:在mysql中给每个表都设置了隐藏字段,有一个是最近修改事务的id,记录每一次操作的事务id,是自增的;另一个是回滚指针,指向上一个版本的事务版本记录地址;
undo log主要的作用是记录回滚日志,存储老版本数据,在内部会形成一个版本链,在多个事务并行操作某一行记录,记录不同事务修改数据的版本,通过回滚指针形成一个链表,链表头部就是最新修改的旧记录,尾部是最早修改的旧记录
readView读视图解决的是一个事务查询选择版本的问题,内部定义了一些匹配规则和当前的一些事务id判断该访问那个版本的数据,不同的隔离级别快照读是不一样的,最终的访问的结果不一样。RC隔离级别下,每一次执行快照读时生成ReadView,RR隔离级别仅在事务中第一次执行快照读时生成读视图,后续复用该读视图
MVCC
多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突
多个事物并发的情况下到底该访问哪个版本
底层实现
-
隐藏字段:
- trx_id(事务id),记录每一次操作的事务id,是自增的
- roll_pointer(回滚指针),指向上一个版本的事务版本记录地址
- row_id,隐藏主键
-
undo log:
- 回滚日志,存储老版本数据
- 版本链:多个事务并行操作某一行记录,记录不同事务修改数据的版本,通过roll pointer指针形成一个链表
-
readView解决的是一个事务查询选择版本的问题
-
根据readView的匹配规则和当前的一些事务id判断该访问那个版本的数据
-
不同的隔离级别快照读是不一样的,最终的访问的结果不一样
- RC:每一次执行快照读时生成ReadView
- RR:仅在事务中第一次执行快照读时生成ReadView,后续复用
-
undo log
回滚日志,在insert、update、delete时产生的便于数据回滚的日志
insert产生的undo log只在回滚时需要,事物提交后可立即被删除
update、delete产生的日志不仅在回滚时需要,MVCC版本访问也需要,不会被立即删除
不同事物或相同事物对同一条记录进行修改,会导致该记录的undo log生成一条记录版本链,链表头部是最新的旧记录,链表尾部是最早的旧记录
ReadView
读视图,是快照读SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事物未提交的id
其中
- Read Committed:RC隔离级别下每次select都生成一个快照读
- Repeatable Read:RR隔离级别下,开启事物后的第一个select才是快照读
ReadView包含四个核心字段:
字段 | 含义 |
---|---|
m_ids | 当前活跃的事务ID集合 |
min_trx_id | 最小活跃事务ID |
max_trx_id | 预分配事务ID,当前最大事务ID+1(因为事务ID是自增的) |
creator_trx_id | ReadView创建者的事务ID |
版本链数据访问规则
trx_id: 代表是当前事务ID。
- trx_id == creator_trx_id?---->可以访问该版本--------->说明数据是当前这个事务更改的。
- trx_id < min_trx_id?---->可以访问该版本--------->成立,说明数据已经提交了。
- trx_id >max_trx_id?---->不可以访问该版本--------->成立,说明该事务是在ReadView生成后才开启。
- min_trx_id <= trx_id <= max_trx_id? ---->如果trx_id不在m_ids中是可以访问该版本的---->成立,说明数据已经提交。
一个一个比,有一个成立就可以读到
不同隔离级别下,生成ReadView的时机不同
- RC隔离级别下,在事物中每一次执行快照读时生成ReadView
- RR隔离级别下,记载事物中第一次执行快照读时生成ReadView,后续复用该ReadView
当前读
读取的是记录的最新版本,读取时还要保证其他并发事物不能修改当前记录,会对读取的记录进行加锁
一般的日常操作select(共享锁)、update、insert、delete(排他锁)都是一种当前读
快照读
读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读
简单的select不加锁就是快照读
标签:事务,快照,记录,trx,版本,MVCC,id From: https://www.cnblogs.com/lmcool/p/17738256.html