【Mysql——MVCC】

介绍

MVCC (多版本并发控制) 是数据库(尤其是 MySQL InnoDB、Oracle、PostgreSQL)实现高并发事务的核心无锁机制 。它通过为每行数据维护多个历史版本,实现 读写互不阻塞,在保证隔离性(ACID 中的 I)的同时大幅提升并发性能。

作用

传统锁机制(悲观锁):

读加共享锁 (S),写加排他锁 (X)

读阻塞写、写阻塞读,高并发下性能瓶颈

MVCC 优势:

读不加锁(快照读),写不阻塞读,读不阻塞写

事务看到的是一致性数据快照,而非实时最新值

完美解决 脏读不可重复读 ,配合间隙锁可解决幻读

原理

InnoDB 通过 隐藏字段 + Undo Log + ReadView 实现 MVCC。

  1. 行记录隐藏字段

每行数据额外隐式存储 3 个字段(用户不可见):

DB_TRX_ID (6 字节):创建 / 最后修改该行的事务 ID(全局递增)

DB_ROLL_PTR (7 字节):回滚指针,指向 Undo Log 中的上一个历史版本

DB_ROW_ID (6 字节):隐藏主键(表无主键时自动生成)

  1. Undo Log(回滚日志)

作用:存储数据修改前的旧版本快照,用于事务回滚 & MVCC 历史读取

类型:

INSERT Undo Log:事务提交后立即删除

UPDATE/DELETE Undo Log:提交后暂存,供快照读读取历史版本,后台定时清理

版本链:

多次 UPDATE/DELETE 时,通过 DB_ROLL_PTR 把所有历史版本串成单向链表(最新版本在表中,旧版本在 Undo Log 里)。

  1. ReadView(读视图 / 一致性快照)

ReadView 是判断 "哪个版本可见" 的核心规则,在快照读(普通 SELECT)时生成。

ReadView 四要素:

m_ids:生成快照时,所有活跃未提交事务 ID 列表

min_trx_id:m_ids 中最小事务 ID

max_trx_id:系统下一个待分配的事务 ID(当前最大 ID + 1)

creator_trx_id:当前事务自己的 ID

版本可见性判断算法

沿版本链从最新到最旧遍历,用 DB_TRX_ID 与 ReadView 比对,第一个满足以下任一条件即可见:

自己修改的:trx_id == creator_trx_id → 可见

已提交的旧版本:trx_id < min_trx_id → 生成快照前已提交 → 可见

未来事务:trx_id >= max_trx_id → 不可见(快照后才创建)

活跃事务区间:min_trx_id ≤ trx_id < max_trx_id

若 trx_id 不在 m_ids → 已提交 → 可见

若 trx_id 在 m_ids → 仍活跃未提交 → 不可见

隔离级别与 ReadView 生成时机

MVCC 只在 RC 和 RR 级别生效;RU(总是读最新)、SERIALIZABLE(加锁读)不使用 MVCC。

  1. READ COMMITTED (读已提交,RC)

每次 SELECT 都生成新 ReadView

特点:总能读到其他事务已提交的最新值

问题:不可重复读(同事务内两次 SELECT 结果可能不同)

  1. REPEATABLE READ (可重复读,RR, MySQL 默认)

事务中第一次 SELECT 时生成 ReadView,后续复用

特点:整个事务内数据一致,看不到其他事务后续提交修改

解决:脏读、不可重复读;配合 Next-Key Lock(查表时不能添加数据) 解决幻读

快照读和当前读

快照读(MVCC 生效),普通 SELECT,不加锁,读取历史版本。

当前读(加锁,MVCC 不生效),读取最新版本并加锁,保证数据强一致性。

SELECT ... FOR UPDATE / LOCK IN SHARE MODE

INSERT / UPDATE / DELETE

相关推荐
l1t1 天前
DeepSeek总结的DuckLake 入门
数据库
Joseph Cooper1 天前
RAG 与 AI Agent:智能体真的需要检索增强生成吗?
数据库·人工智能·ai·agent·rag·上下文工程
light blue bird1 天前
主子端台二分法任务汇总组件
前端·数据库·.net·桌面端winform
DevilSeagull1 天前
MySQL(2) 客户端工具和建库
开发语言·数据库·后端·mysql·服务
小李来了!1 天前
Navicate/plsql连接Oracle数据库教程
数据库·oracle
苍煜1 天前
慢SQL优化实战教学
java·数据库·sql
zhaoyong2221 天前
MySQL 存储过程中字符集与排序规则不匹配导致查询性能下降的解决方案
jvm·数据库·python
sinat_383437361 天前
golang如何从Python转型Go开发_golang从Python转型Go开发攻略
jvm·数据库·python
远洪1 天前
claude code 国内安装使用
数据库·mysql
雨辰AI1 天前
SpringBoot3 + 人大金仓 V9 微服务监控实战|Prometheus+Grafana+SkyWalking 全链路监控
数据库·后端·微服务·grafana·prometheus·skywalking