一只大象对一只骆驼说:“为什么你的背那么驼?” 骆驼回答:“因为我想离地近一点。” 大象疑惑地问:“那你为什么还长着那么长的脖子?” 骆驼笑着说:“这样我可以看得更远,看看谁在背后说我背驼!”
多版本并发控制(MVCC,Multi-Version Concurrency Control)是一种用于解决数据库并发问题的机制。它允许多个事务并发运行而不互相阻塞,同时提供一致的数据视图,提高了数据库的性能和吞吐量。MVCC 是 PostgreSQL、MySQL(InnoDB 引擎)等现代数据库中常用的并发控制技术。
1. MVCC 的核心理念
MVCC 的核心思想是通过为每个事务提供一个数据快照(snapshot)来实现并发控制,而不锁定数据行。这意味着:
读操作不阻塞写操作。
写操作不阻塞读操作。
提供事务隔离级别的支持,例如可重复读(Repeatable Read)和快照隔离(Snapshot Isolation)。
MVCC 实现这一机制的基础是通过 记录多版本的数据快照,并根据事务的时间戳或标识符来确定数据的可见性。
2. MVCC 的工作机制
MVCC 的实现依赖于以下几个核心组件:
(1) 数据版本
每个数据行(或元组)保存多个版本,每个版本对应一个事务操作的结果。
每个版本包含:
创建事务 ID(
xmin
): 表示该版本是由哪个事务创建的。删除事务 ID(
xmax
): 表示该版本是由哪个事务删除的(如果适用)。其他元信息: 包括行的内容、指向下一个版本的指针等。
(2) 事务时间戳
数据库为每个事务分配一个唯一的事务 ID(Transaction ID,
TXID
)。事务的开始时间和结束时间决定了事务能够看到哪些数据版本。
(3) 数据可见性规则
在 MVCC 中,每个事务只能看到满足以下条件的数据版本:
数据版本的
xmin
必须早于事务的开始时间(事务开始之前创建的数据是可见的)。数据版本的
xmax
必须为空,或者大于事务的开始时间(表示数据未被后续事务删除)。
(4) 数据读取与写入
读取: 事务通过检查数据版本的
xmin
和xmax
来确定某行是否可见。写入: 写操作通常会创建一个新版本的数据,而不是直接覆盖旧版本。
3. MVCC 在不同隔离级别中的表现
数据库隔离级别决定了事务之间的数据可见性。以下是 MVCC 在不同隔离级别中的表现:
(1) Read Uncommitted
最低隔离级别,事务可以看到未提交事务的修改。
MVCC 不需要特别处理,直接读取最新版本的数据。
(2) Read Committed
只允许事务读取已提交的数据。
使用 MVCC 时,事务只能看到在其开始之前已经提交的数据版本。
(3) Repeatable Read
在一个事务中,任何数据读取操作都会看到相同的快照。
使用 MVCC 时,事务读取的快照固定在事务开始时。
数据写入操作会创建新的数据版本,而不影响当前事务的快照。
(4) Serializable
最高隔离级别,所有事务看起来像是顺序执行的。
MVCC 通过检测写冲突和序列化冲突来实现。
4. MVCC 的实现细节
以下是 MVCC 在 PostgreSQL 和 MySQL(InnoDB 引擎)中的具体实现:
(1) PostgreSQL 的 MVCC 实现
PostgreSQL 使用行级别的多版本存储。
每个数据行(Tuple)有
xmin
和xmax
两个字段:xmin
:指示哪个事务创建了这条记录。xmax
:指示哪个事务删除了这条记录。事务通过对比自身的事务 ID 和
xmin
/xmax
来判断数据是否可见。数据修改时:
不会直接覆盖原来的行,而是创建一个新的版本。
原来的版本保留,直到不再有事务需要它(VACUUM 操作清理无用数据)。
(2) MySQL(InnoDB 引擎)的 MVCC 实现
InnoDB 使用隐藏的系统字段来实现 MVCC,包括:
DB_TRX_ID
:记录创建该行的事务 ID。DB_ROLL_PTR
:指向回滚段(Rollback Segment),用于存储旧版本数据。事务通过回滚段访问历史版本数据,确定数据的可见性。
数据修改时:
新版本会写入当前行。
旧版本存储在回滚段中。
5. MVCC 的优点
高并发性能
读写操作互不阻塞,提高了数据库的并发性能。
实现一致性视图
每个事务都有自己的快照视图,能够保证一致性读。
支持事务隔离
通过数据版本管理,实现不同隔离级别的事务要求。
避免死锁
通过多版本机制,降低了锁冲突的可能性。
6. MVCC 的缺点
存储空间消耗
数据修改会产生多个版本,占用额外的存储空间。
需要定期清理(如 PostgreSQL 的 VACUUM 或 MySQL 的 purge 操作)。
实现复杂性
数据版本的管理和可见性判断逻辑较复杂。
在高并发情况下,可能增加事务处理的开销。
延迟清理的副作用
长时间运行的事务会阻止旧版本的回收,导致存储空间膨胀。
7. 使用 MVCC 的数据库
PostgreSQL:MVCC 是其核心功能,支持行级多版本并发。
MySQL(InnoDB 引擎):通过隐藏字段和回滚段实现 MVCC。
Oracle:使用回滚段实现多版本并发。
SQL Server:通过启用快照隔离支持类似 MVCC 的机制。
总结
MVCC 是一种通过多版本数据快照来实现高并发和一致性读的技术。它在 PostgreSQL 和 MySQL 等数据库中的应用,显著提升了事务处理的性能和隔离性。MVCC 的优势在于减少锁竞争、提高读写性能,但需要额外的存储空间和管理机制来处理版本清理问题。选择支持 MVCC 的数据库,可以在性能和一致性之间找到更好的平衡点。




