当前位置: 首页 > news >正文

MySQL 系统学习 第四阶段:MySQL 高级 第六节:MVCC(Multi-Version Concurrency Control,多版本并发控制)

前面我们学习:

  • 事务:保证一组操作的一致性
  • 锁:解决多个事务同时修改数据的问题

但是有一个问题:

如果所有查询都加锁,数据库还能高并发吗?

答案:

不能。

所以 InnoDB 引入了:

MVCC

读操作不需要加锁,也能读取一致的数据版本


一、为什么需要 MVCC?

假设:

用户表:

id | name | age 1 | Tom | 20

现在两个事务:


事务A:

查询:

SELECT * FROM user WHERE id=1;

事务B:

修改:

UPDATE user SET age=21 WHERE id=1;

如果没有 MVCC:

事务A读取时:

必须等待事务B完成。

结果:

并发能力下降。


有 MVCC:

事务A:

读取旧版本:

age=20

事务B:

修改新版本:

age=21

两个事务互不影响。


二、MVCC 的核心思想

一句话:

数据库保存数据的多个版本,读取时根据事务规则选择合适版本。

例如:

数据:

版本1: age=20 版本2: age=21 版本3: age=22

不同事务:

看到不同版本。


类似 Git:

commit1 | commit2 | commit3

可以查看不同历史版本。


三、InnoDB 实现 MVCC 依赖什么?

主要依靠三个东西:

1. 隐藏字段

2. Undo Log(回滚日志)

3. Read View(读视图)

⭐⭐⭐⭐⭐


四、隐藏字段

InnoDB 每一行数据实际上有隐藏字段。

例如:

用户表:

CREATE TABLE user( id INT, name VARCHAR(20) );

实际上:

InnoDB 保存类似:

id name 隐藏字段: ---------------- DB_TRX_ID DB_ROLL_PTR

① DB_TRX_ID

事务ID。

表示:

哪个事务修改了这条数据。

例如:

事务100修改 DB_TRX_ID=100

② DB_ROLL_PTR

回滚指针。

指向:

上一个版本的数据。

形成版本链。


五、Undo Log(回滚日志)

Undo Log:

作用:

保存数据修改之前的版本。

例如:

原数据:

age=20

事务A修改:

UPDATE user SET age=21;

数据库保存:

Undo Log:

age=20

现在:

当前数据:

age=21

历史数据:

age=20

形成:

当前版本 | | Undo Log | 旧版本

六、版本链是什么?

例如:

数据不断修改:

第一次:

age=20

事务101:

age=21

事务102:

age=22

最终:

age=22 ↓ age=21 ↓ age=20

这就是:

版本链。


七、Read View(读视图)⭐⭐⭐⭐⭐

这是 MVCC 最核心概念。

Read View:

事务进行普通查询时创建的一份可见性规则。

简单理解:

它决定:

我应该看到哪个版本的数据。


例如:

当前数据:

版本3 | 版本2 | 版本1

事务A:

创建 Read View。

规则:

可能看到:

版本2

而不是最新:

版本3

八、MVCC 如何判断数据是否可见?

InnoDB 会比较:

数据版本中的:

DB_TRX_ID

和:

当前事务的 Read View。


简单理解:

如果:

修改数据的事务已经提交:

可以看到。


如果:

修改数据的事务还没有提交:

不能看到。


九、MVCC 解决什么问题?

主要解决:

1. 读写冲突

例如:

事务A:

读取。

事务B:

修改。

不用互相等待。


2. 提高并发

传统方式:

读 | 加锁 | 等待写

MVCC:

读 | 读取历史版本

十、MVCC 与隔离级别关系

MySQL InnoDB 默认:

REPEATABLE READ

可重复读。

为什么可以做到?

因为:

MVCC。


例如:

事务A:

第一次查询:

余额=1000

事务B:

修改:

余额=500

提交。


事务A:

再次查询:

仍然:

余额=1000

因为:

使用同一个 Read View。


十一、MVCC 如何解决不可重复读?

不可重复读:

原因:

第二次读取看到最新数据。


MVCC:

第一次查询:

创建 Read View:

看到版本1

第二次查询:

继续使用:

版本1

所以:

结果一致。


十二、MVCC 和锁的区别

很多人容易混淆。

MVCC
解决问题读一致性并发修改冲突
方式版本控制阻塞等待
是否阻塞通常不阻塞可能阻塞
主要对象读操作写操作

例如:

普通查询:

SELECT * FROM user;

使用:

MVCC。


修改:

UPDATE user SET age=20;

使用:

锁。


十三、普通 SELECT 和 FOR UPDATE 区别

普通查询:

SELECT * FROM user WHERE id=1;

特点:

  • 不加锁
  • 使用 MVCC
  • 读取快照数据

当前读:

SELECT * FROM user WHERE id=1 FOR UPDATE;

特点:

  • 加锁
  • 读取最新数据
  • 用于修改前查询

例如:

库存扣减:

必须:

SELECT stock FROM product WHERE id=1 FOR UPDATE;

不能使用普通 SELECT。


十四、企业开发中的应用

场景1:订单查询

普通:

SELECT * FROM orders WHERE user_id=100;

使用:

MVCC。

高并发:

没问题。


场景2:库存修改

需要:

SELECT stock FROM product WHERE id=1 FOR UPDATE;

使用:

锁。

保证不会超卖。


十五、本节总结

概念作用
MVCC多版本并发控制
目的提高数据库并发能力
Undo Log保存历史版本
版本链保存数据变化记录
Read View判断版本是否可见
普通SELECT使用MVCC
FOR UPDATE使用锁
RR隔离级别依赖MVCC实现可重复读

🎯 本节核心一句话:

MVCC 通过保存数据历史版本,让读操作不需要加锁也能看到一致的数据,是 InnoDB 高并发能力的核心机制。

http://www.cnnetsun.cn/news/3359750.html

相关文章:

  • 从零实现C++哈希表:深入理解unordered_map底层原理与性能优化
  • C++错误处理实战:从错误码到异常安全与RAII资源管理
  • Android小游戏开发实战:从Canvas绘制到游戏循环设计
  • static关键字的四种用法:面试官问“static有几种用法”,90%的人答不全
  • 类与对象:面试官让我用机器人传感器解释封装,我讲了五分钟
  • 01 Java 程序员为什么要聊 AIGC?现在面试到底卷成什么样了
  • Unity DOTS避坑指南:从OOP思维到ECS高性能开发的实战解析
  • SVG 与 Canvas 在前端开发中的区别与应用场景详解
  • C++ CSV解析库RapidCSV:单文件集成与高性能数据处理实践
  • Pandas数据清洗速查手册:12个高频函数实战指南
  • 多家 CDN 试用期地图对比选型:同域不同商的科学方法
  • GPT-5.6 功能介绍:Sol、Terra、Luna 模型定位、核心能力与适用场景
  • MCP3551与PIC18F2680构建高精度数据采集系统
  • 手把手教你学 Simulink—— 新能源(光伏)并网逆变器 MPPT + 并网逆变联合仿真(Boost + 三相 PWM 逆变 + PQ 控制)
  • 多机AI代理编排实战:解决凭证冲突、资源分配与任务同步难题
  • 从零到一:手把手教你用LabelImg构建你的第一个AI数据集
  • 挑战一周学会ROS(第二天)
  • 从让 AI 写代码到让 AI 按规则工作:嵌入式工程师的实践思考
  • 基于XGBoost+LSTM双模型的股票预测系统——“智语析金”智能投研平台
  • VC++机器视觉实战:从OpenCV集成到工业级算法优化
  • 【提示词工程 03 对话模型对齐】从基础模型到可用助手的演进
  • 21-缓存越用越脏-给本地数据加版本过期和重建策略
  • AI Token工厂爆发:清华师生创业半年融资10亿,背后是门什么生意
  • 现代C++软件架构设计:从核心原则到工程实践
  • AI 前沿日报 | 2026年7月13日
  • RAG中PDF文档的处理和存储(二):Markdown文档的分块处理与入库
  • 运算符与表达式
  • 工业信号采集:FOD4216光耦与PIC18F25J11的抗干扰方案
  • HybridCLR热更新开发中UnityLinker.exe报错的系统性排查与解决方案
  • 施工企业合同管控工具测评:蓝燕云全生命周期管理能力