当前位置: 代码网 > it编程>数据库>Mysql > MySQL多版本并发控制(MVCC)示例详解

MySQL多版本并发控制(MVCC)示例详解

2026年08月15日 Mysql 我要评论
前言多版本并发控制(mvcc,multi-version concurrency control)是一种实现高并发事务隔离的核心机制。它通过保存数据的多个历史版本,让读写操作不堵塞,从而避免了传统锁机

前言

多版本并发控制(mvcc,multi-version concurrency control)是一种实现高并发事务隔离的核心机制。它通过保存数据的多个历史版本,让读写操作不堵塞,从而避免了传统锁机制带来的瓶颈。

1. 核心思想

mvcc 为每个事务提供一个数据快照(snapshot),事务读取的是某个时间点的一致性数据版本,而不是最新的数据,如此一来:

  • 读操作不需要等待写操作释放锁

  • 写操作也不需要等待读操作完成

  • 实现了非阻塞读

2. 关键数据结构

innodb通过undo log + 隐藏字段 + read view实现mvcc。

2.1 undo log

undo log是 mvcc 的版本链基础:

  • 插入undo log记录主键,用于回滚时删除

  • 删除:标记删除,undo log记录完整行数据,用于恢复

  • 更新undo log记录旧值,形成版本链

2.2 隐藏字段

每行记录自动添加,对用户不可见,innodb自动维护

字段名大小作用
db_trx_id6 字节创建该版本的事务id(最后修改此行的事务)
db_roll_ptr7 字节回滚指针,指向undo log的上一个版本
db_row_id6 字节隐藏主键

2.3 read view

read view是事务执行快照读时生成的一致性试图,决定事务能看待哪些版本的数据。

read view包含的关键字段:

字段说明
creator_trx_id创建该read view的事务id
m_ids生成read view时,活跃(未提交)事务id列表
min_trx_idm_ids中的最小值
max_trx_id生成read view时,系统分配的下一个事务id(全局最大加 1)

3. 可见性判断规则

当事务读取某行数据时,通过比较该行的db_trx_idread view来判断可见性:

判断流程(对版本链从上到下遍历):

1. 如果 db_trx_id == creator_trx_id → 可见(自己修改的)
2. 如果 db_trx_id < min_trx_id → 可见(已提交事务修改的)
3. 如果 db_trx_id >= max_trx_id → 不可见(将来事务修改的,未发生)
4. 如果 min_trx_id <= db_trx_id < max_trx_id:
   - 如果 db_trx_id 在 m_ids 中 → 不可见(未提交事务修改的)
   - 如果 db_trx_id 不在 m_ids 中 → 可见(已提交事务修改的)

如果不可见,就沿着 db_roll_ptr 找上一个版本,重复判断。

4. 两种读操作

读类型说明实现方式
快照读(snapshot read)不加锁,读取历史版本基于 mvcc + read view
当前读(current read)读取最新版本,需要加锁select ... for update/ dml 语句

只有普通select是快照读,其他操作(updatedelete等)都是当前读,需要加锁

5. 与事务隔离级别的关系

隔离级别mvcc 行为
read uncommited不适用 mvcc,直接读最新版本(可能脏读)
read commited每次select都生成新的read view,能看到其他事务已提交的最新修改
repeatable read事务开始时生成一个read view,整个事务复用,保证可重复读
serializable不使用 mvcc,所有操作加锁

mysql 默认隔离级别为repeatable read

附:rc、rr级别下的innodb快照读有什么不同:

1、首先mysql四种隔离级别:

1)未提交读(read uncommited)脏读

2) 已提交读 (read commited)简称(rc) 不可重复读

3)可重复读(repeatable read)简称(rr )

4)可串行化(serializable)

2、因为read view生成时机的不同,从而造成rc、rr级别下快照读的结果的不同:

1)、在rr级别下的某个事务的对某条记录的第一次快照读会创建一个快照即read view将当前系统活跃的其他事务记录起来,此后调用快照读的时候,还是使用的是同一个read view, 所以只要当前事务在其他事务提交更新之前使用过快照读,那么之后的快照读使用都是同一个read view,所以对之后的修改不可见。

2)、在rr级别下,快照读生成readview时,read view会记录此时所有其他活跃事务的快照,这些事务的修改对于当前事务都不可见的, 而早于read view创建的事务所做的修改均是可见。

3)、在rc级别下,事务中,每次快照读都会新生成一个快照和read view,这就是我们在rc级别下的事务中可以看到别的事务提交的更新的原因。

总结 

到此这篇关于mysql多版本并发控制(mvcc)的文章就介绍到这了,更多相关mysql多版本并发控制内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com