MVCC是如何工作的?
核心概念:什么是 MVCC?
MVCC 的中文翻译为多版本并发控制。
它是一种数据库管理系统中常用的技术,用于高效地处理高并发场景下的读写操作,在保证数据一致性的同时,大幅提升性能。
它的核心思想非常直观:不为数据行加锁,而是为每个数据修改创建多个版本。
为什么要用 MVCC?—— 解决并发问题
在没有 MVCC 的情况下,数据库通常通过锁来保证并发事务的数据一致性。这会带来两个主要问题:
- 读写冲突:当一个事务正在写数据(更新、删除)时,它会锁定数据行,其他事务(即使是读操作)必须等待锁释放才能进行。这严重影响了读性能。
- 写写冲突:多个写操作同时进行时,只能串行执行,效率低下。
MVCC 完美地解决了读写冲突的问题。它让读操作永远不用等待写操作,写操作也不用等待读操作,使得读写操作可以并发执行,极大地提高了数据库在读写混合场景下的吞吐量。
MVCC 是如何工作的?
MVCC 通过为数据项创建多个“快照”版本来实现。每个事务在某个时间点看到的数据,是数据库在该时间点的一个一致性快照。
实现 MVCC 通常需要三个关键技术点:
1. 数据的多个版本
数据库中的每一行数据都不止有一个当前版本,它还可能有多个由之前事务创建的旧版本。这些版本会通过“回滚指针”在数据库中链接起来,形成一个版本链。
2. 事务的版本号(或时间戳)
每个事务在开始时都会被分配一个唯一的、自增的事务 ID (Transaction ID)。
这个 ID 定义了事务的时间顺序。
3. 快照的可见性规则
这是 MVCC 最核心的部分。当一个事务要读取数据时,数据库如何决定它能看到哪个版本的数据?
规则大致如下:数据行的每个版本都记录着创建它的事务 ID (create_trx_id
) 和删除(或失效)它的事务 ID (delete_trx_id
)。
一个数据版本对当前事务可见,必须满足以下条件之一:
该版本的 create_trx_id
小于等于当前事务 ID,并且:
该版本的 delete_trx_id
要么未定义(表示还未被删除),要么大于当前事务 ID(表示它是在当前事务启动之后才被删除的)。
简单来说:一个事务只能看到在它开始之前就已经提交的数据版本,而看不到在它开始之后才提交的修改或未提交的修改。
MVCC 的优点和缺点
优点:
高并发性能:读写互不阻塞,这是最大的优点,非常适合读多写少的应用场景。
避免了死锁:因为读操作不需要加锁。
保证事务的隔离性:轻松实现了
READ COMMITTED
和REPEATABLE READ
隔离级别。
缺点:
额外的存储开销:需要为每一行数据存储多个版本,当旧版本数据很多时,会占用更多磁盘空间。
维护 overhead:数据库需要定期清理(Purge)不再被任何事务需要的旧数据版本,这个过程称为“垃圾回收”。
哪些数据库使用了 MVCC?
MVCC 是许多现代数据库系统的核心功能,包括:
- MySQL 的 InnoDB 存储引擎
- PostgreSQL
- Oracle Database
- Microsoft SQL Server (2014之后的版本,叫 Accelerated Database Recovery)
- SQLite
总结
特性 | 解释 |
---|---|
全称 | 多版本并发控制 (Multi-Version Concurrency Control) |
目的 | 解决高并发下的读写冲突,提升数据库性能,无需加锁读。 |
核心思想 | 为数据保留多个历史版本,每个事务根据自己的“时间点”看到不同的数据快照。 |
关键实现 | 1. 数据行多版本 2. 事务ID 3. 数据可见性规则 |
主要优点 | 读写不阻塞,并发性能高,避免死锁。 |
主要缺点 | 存在存储空间开销,需要垃圾回收旧数据版本。 |