mvcc 简介

MVCC(Multi-Version Concurrency Control,多版本并发控制)是数据库中用于解决并发访问冲突的核心机制,广泛应用于InnoDB、PostgreSQL等主流数据库。其核心思想是为数据维护多个版本,使得读写操作可以并发执行而不互相阻塞,从而在保证事务隔离性的同时提升并发性能。

为什么需要MVCC?

传统的并发控制依赖锁机制(如行锁、表锁),但锁会导致读写冲突(例如:读操作需要等待写操作释放锁,或写操作等待读操作释放锁),在高并发场景下严重影响性能。

MVCC通过让读操作访问数据的历史版本,避免了对当前写入版本的依赖,从而实现"读不加锁、写不阻塞读",极大提升了并发效率。

MVCC的核心原理

MVCC的实现依赖三个关键组件:隐藏列undo日志Read View(读视图)

1. 隐藏列:数据版本的"身份标识"

数据库表中的每行数据,除了用户定义的列外,还会隐含几个系统列(以InnoDB为例):

  • DB_TRX_ID:记录最后一次修改该数据行的事务ID(6字节)。
  • DB_ROLL_PTR:回滚指针(7字节),指向该数据行的上一个版本(存储在undo日志中)。
  • DB_ROW_ID:行唯一标识(6字节),当表没有主键时,InnoDB会用它生成聚簇索引。

这些隐藏列是MVCC追踪数据版本的基础。

2. undo日志:数据版本的"历史档案"

当事务修改数据时,数据库会先将数据的旧版本写入undo日志(回滚日志),然后再更新当前数据行。

  • 例如:事务T1修改了一行数据,旧版本会被存入undo日志,当前数据行的DB_ROLL_PTR指向这个旧版本;若事务T2再次修改该行,新的旧版本(T1修改后的版本)会被存入undo日志,DB_ROLL_PTR更新为指向T2的旧版本,形成一条版本链(通过回滚指针串联的历史版本)。
  • undo日志的另一个作用是事务回滚:若事务执行失败,可通过undo日志恢复数据到修改前的状态。
3. Read View:判断版本可见性的"规则"

Read View(读视图)是事务在读取数据时生成的一个"快照",用于判断当前事务能看到哪个版本的数据。它包含四个核心参数:

  • m_ids:当前活跃事务的ID集合(即尚未提交的事务)。
  • min_trx_id:m_ids中最小的事务ID(当前活跃事务的最小ID)。
  • max_trx_id:数据库下一个将要分配的事务ID(大于当前所有活跃事务ID)。
  • creator_trx_id:生成该Read View的事务自身的ID。
4. 可见性判断规则

当事务读取数据时,会通过Read View判断数据版本链中哪个版本对自己可见,规则如下(假设数据版本的DB_TRX_IDtrx_id):

  1. trx_id == creator_trx_id:该版本是当前事务自己修改的,可见。
  2. trx_id < min_trx_id:修改该版本的事务已提交(因为其ID小于所有活跃事务ID),可见。
  3. trx_id >= max_trx_id:修改该版本的事务是在当前事务之后启动的,不可见。
  4. min_trx_id <= trx_id < max_trx_id
    • trx_idm_ids中(该事务仍活跃):不可见。
    • trx_id不在m_ids中(该事务已提交):可见。

如果当前版本不可见,事务会通过DB_ROLL_PTR回溯到上一个版本,重复判断,直到找到可见版本或版本链结束(此时返回空)。

MVCC与事务隔离级别的关系

MVCC的行为会根据事务隔离级别调整,核心差异在于Read View的生成时机

  • Read Committed(读已提交):每次执行查询时都会生成新的Read View。因此,同一事务中两次查询可能看到不同的结果(因为中间可能有其他事务提交)。
  • Repeatable Read(可重复读,InnoDB默认):仅在事务第一次执行查询时生成Read View,后续查询复用该视图。因此,同一事务中多次查询看到的结果一致(避免了不可重复读)。

(注:Serializable隔离级别通常不依赖MVCC,而是通过加锁实现;Read Uncommitted直接读取最新版本,不适用MVCC。)

MVCC的优势

  1. 读写不冲突:读操作无需加锁,直接访问历史版本;写操作仅锁定当前版本,不阻塞读,极大提升并发性能。
  2. 简化隔离级别实现:通过Read View的生成时机和可见性规则,自然实现了Read Committed和Repeatable Read隔离级别的语义。
  3. 避免锁竞争:减少了传统锁机制的阻塞和等待,降低了死锁风险。

总结

MVCC通过隐藏列记录版本标识undo日志维护历史版本链Read View判断可见性,实现了"多版本并发访问"。其核心价值是在保证事务隔离性的前提下,最大化读写并发效率,是现代数据库高性能的关键机制之一。

相关推荐
稻香味秋天1 小时前
单元测试指南
数据库·sqlserver·单元测试
JosieBook2 小时前
【数据库】Apache IoTDB数据库在大数据场景下的时序数据模型与建模方案
数据库·apache·iotdb
全栈胖叔叔-瓜州2 小时前
关于微软最新数据库引擎sqlserver2025 关于向量距离函数调用的问题
数据库·microsoft
全栈小52 小时前
【Rust】从0到1开发和运行Web相关功能,并简单实现数据库连接和查询
数据库·rust
墨辰JC2 小时前
基于STM32标准库的FreeRTOS移植与任务创建
数据库·stm32·嵌入式硬件·freertos
R.lin2 小时前
MongoDB知识点与技巧总结
数据库·mongodb
幽水-椰子糖2 小时前
达梦守护搭建
数据库·达梦
q***3753 小时前
Spring Boot 从 2.7.x 升级到 3.3注意事项
数据库·hive·spring boot
王小小鸭3 小时前
【Oracle APEX开发小技巧17】交互式网格操作按钮根据条件/状态设置能否被点击生效
数据库·oracle·oracle apex