理解 mvcc

mvcc 多版本并发控制,

提高数据库的并发性能 ------ 让"读"和"写"互不阻塞!

什么意思?

传统方式:读数据要加"读锁",写数据要加"写锁",读写冲突 → 等待

MVCC 方式:读走快照,写走新版本,互不影响 ✅

🎯 所以,MVCC 的诞生,首先是为了性能

然后 MVCC + "可重复读"隔离级别,确实能防止快照读下的幻读 ,

幻读就是 如果事务A 第一次查询结果为3条, 这个事务还没结束, 其他事务 插入了 数据 并且 已经提交 , 第二次查询就是 4条, 一个事务同样查询条件的 两次查询的结果不一致, 这就是幻读

在事务开始时,看到的是一个属于自己的"快照",即使别人提交了新数据,你也看不到,直到事务结束。

mvcc 的工作原理是 : 数据库(比如 MySQL InnoDB)会给每行数据加上几个"隐藏字段" :

最后修改这行的事务ID ,

指向上一个版本的"回滚指针"

当你更新一行数据时,旧数据不会立刻被覆盖,而是:

保存为一个"旧版本";

新数据作为一个"新版本";

通过指针连成一条"版本链"。

你执行查询时,数据库根据你的事务开始时间,决定你该看到哪个版本的数据。

这些"旧版本"什么时候删除?

当确认没有任何事务还需要它时,MySQL 的后台线程会清理掉这些旧版本,释放空间

当然,如果仅仅是 mvcc 是不能防止当前读 的幻读的, 并不能 防止当前读的幻读 , 比如一个事务中, 同时有两条 相同查询条件的 sql, 其中 有条语句 加了 for update , 那加了 for update 的语句走的不是快照读, 是当前读( 读取最新的) , 那两次查询的结果不一样 , 那这就是幻读了

如果 加锁, mvcc 间隙锁 , 其他事务插入不了数据了, 或者即将插入的地方在锁的范围内 (在间隙锁范围内), 那就肯定不会幻读 . 比如:

sql 复制代码
-- 事务A
BEGIN;
SELECT * FROM users WHERE age > 25 FOR UPDATE;  -- 加锁,包括间隙锁
-- 此时事务B尝试插入 age=28
-- ❌ 事务B会被阻塞,无法插入,直到事务A提交
SELECT * FROM users WHERE age > 25 FOR UPDATE;  -- 仍然只有原来的记录
COMMIT;
相关推荐
for_ever_love__5 小时前
MySQL 索引类型全解:B+Tree / Hash / R-Tree / 全文 的底层差异,以及一次性建对的选型表
数据库·mysql·b+树·唯一索引·全文索引·索引类型·索引分类
天天喝旺仔15 小时前
MySQL 索引原理与慢查询优化实战:从 B+ 树到执行计划调优
数据库·sql·mysql·性能优化
m0_6464299716 小时前
MySQL 初始化 SQL 中文乱码问题总结
数据库·sql·mysql
实战派K8S&DB16 小时前
TDSQL 核心模块与进程体系
运维·数据库·分布式·sql·mysql
Lost_the_wind16 小时前
MySQL 学习笔记三
笔记·学习·mysql
腾科IT教育17 小时前
Oracle OCP和MySQL OCP怎么选?方向对比指南
mysql·oracle·ocp·oracle ocp·ocp怎么选·mysql ocp
用户4603812919419 小时前
别人都 commit 了,为什么我的 select 还是旧值?图解 MySQL MVCC
mysql
毕业设计70321 小时前
(免费领源码)django空气净化器销售系统09218- java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
python·scrapy·mysql·pycharm·django·flask·pandas
CJi0NG1 天前
【自用】MySQL-事务
数据库·mysql
VX_bysjlw9851 天前
数码设备销售网站设计与实现39138-计算机毕设原创(免费领源码+带部署教程)
java·vue.js·spring boot·mysql·tomcat·mybatis·idea