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

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

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

 

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

idnamecreate_versiondelete_version
1 张三 1  
2 李四 2  

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

select * from user where id<=3;

 

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

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

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

idnamecreate_versiondelete_version
1 张三 1  
2 李四 2  
1 张三三 4  

 

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

idnamecreate_versiondelete_version
1 张三 1  
2 李四 2 5
1 张三三 4  

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

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插入一条 王五的数据,结果是这样:

idNamecreate_versiondelete_version
1 张三 1  
2 李四 2  
3 王五 7  

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

posted @   唯一客服系统开发笔记  阅读(266)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2020-02-23 [Linux] ubuntu下yarn依赖管理工具的安装和使用
2019-02-23 [Go] golang无缓冲通道实现工作池控制并发
2019-02-23 [Go] golang的range循环遍历通道
2019-02-23 [Go] golang缓冲通道实现资源池
2019-02-23 [Go] golang类型断言
2016-02-23 [android] 点击事件的四种写法
点击右上角即可分享
微信分享提示
1
chat with us