目录
1. 什么是MVCC(多版本并发控制)
推荐我的另外一篇文章:【Mysql篇】什么是MVCC?什么是快照读?版本链?什么是readView?MVCC如何实现事务的隔离性?
1. 定义(Mutli Version Concurreny Control)
MVCC其实就是一个多版本并发控制,即多个不同版本的数据实现并发控制的技术,其基本思想是为每次事务生成一个新版本的数据,在读数据时选择不同版本的数据即可以实现对事务结果的完整性读取。
2. MVCC的组成要素
1. 每条记录有三个隐藏列
1. 事务ID(DB_TRX_ID)
记录创建这条记录/最后一次修改该记录的事务ID
2. 回滚指针(DB_ROLL_PTR)
指向这条记录的上一个版本
3. 隐藏主键(DB_ROW_ID)
隐含的自增ID。现在不知道干嘛用的
2. undo_log日志
每次操作都会生成一条undo_log日志,分为insert undo log和update undo log
3. read-view(读视图)
[未提交的事务id] + 最大事务id
1.什么时候生成Read-View?
要看数据库的隔离级别:
- 可重复读返回的是第一次查询生成的【read-view】
- 读已提交每次都会重新生成一个新的【read-view】
3. MVCC实现原理
查询的时候会读取出【read-view】,并根据read-view从undo_log日志中最新的记录一次往下找,查找规则如下:
从最新的undolog开始遍历,下面的当前undolog对应的事务id是否可读的判断条件:
-
如果当前记录:事务id < 未提交事务的最小id,则可读
说明找个事务id已经提交完了
-
如果当前记录:最小id <= 事务id <= 事务的最小id,则判断事务id是否在未提交事务id的数组中,如果在则不可读(如果只有自己还是可读)
-
如果当前记录:事务id > 事务的最大id,则不可读
有点晦涩难懂:具体的操作看这篇文章,写的非常棒!
https://www.cnblogs.com/boluopabo/p/13111961.html
4. 例子
图片来源:https://www.cnblogs.com/boluopabo/p/13111961.html
本次操作一共涉及4个事务,先求read-view,未提交的事务有1和3,最大事务id是3,所以read-view是【1,3】3。
后面会遍历undolog,从最新的开始,知道满足上面可读条件。
5. MVCC主要有什么作用
1. 非阻塞的并发读写
提高并发读写性能,操作时会生成事务id,能够更好地解决读-写冲突,不加锁、非阻塞的并发读
2. 实现读已提交和可重复读
MVCC只能实现读已提交和可重复读;如果是读未提交,那么每次查询都能获取最新的修改值。
1. 问:MVCC如何实现读已提交
每次查询的时候生成一个新的【read-view】,然后去【undo】日志中寻找符合结果的一条数据
2. 问:MVCC如何实现可重复读(复用read-view)
第一次查询的时候生成一个新的【read-view】,后面的查询会继续沿用第一次的【read-view】,然后找出一个可读的数据