[MySQL]事务的MVCC原理与幻读

2021年02月24日 阅读数:5
这篇文章主要向大家介绍[MySQL]事务的MVCC原理与幻读,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

首先要了解MVCC,MVCC叫作多版本并发控制,实际上就是保存了数据在某个时间节点的快照并发

咱们每行数实际上隐藏了两列,建立版本号,过时(删除)版本号,每开始一个新的事务,版本号都会自动递增编辑器

 

拿user表举例子,假设咱们插入两条数据,他们实际上应该长这样 , 建立版本号是递增的。spa

id name create_version delete_version
1 张三 1  
2 李四 2  

这时候假设小明去执行查询,此时也是会默认开启一个事务 当前版本就是 current_version=3索引

select * from user where id<=3;事务

 

同时,小红在这时候开启事务去修改id=1的记录,小红事务版本是 current_version=4io

update user set name='张三三' where id=1;table

小红执行成功后的结果是这样的原理

id name create_version delete_version
1 张三 1  
2 李四 2  
1 张三三 4  

 

同时 , 还有小黑在删除id=2的数据,小黑的版本是 current_version=5,小黑执行后结果是这样的。date

id name create_version delete_version
1 张三 1  
2 李四 2 5
1 张三三 4  

因为MVCC的原理是查找建立版本小于或等于当前事务版本,删除版本为空或者大于当前事务版本,小明的真实的查询应该是这样select

select * from user where id<=3 and create_version<=3 and (delete_version>3 or delete_version is null);

因此小明最后查询到的id=1的名字仍是'张三',而且id=2的记录也能查询到。这样作是为了保证事务读取的数据是在事务开始前就已经存在的,要么是事务本身插入或者修改的

 

幻读是这样的 , 好比下面的增长用户的例子 ,假定用户名是惟一索引不容许重复

小明想要插入一条王五的数据 , 开启事务current_version=6查询名字为 '王五'的记录,发现不存在。

同时小红开启事务current_version=7插入一条 王五的数据,结果是这样:

id Name create_version delete_version
1 张三 1  
2 李四 2  
3 王五 7  

小明执行插入名字'王五'的记录,发现惟一索引冲突,没法插入,查询的时候分明看不到王五 , 可是插入老是说重复了 ,  这就是幻读。