MVCC 是什么?解决了什么问题?

6 阅读6分钟

MVCC(Multi-Version Concurrency Control)是 多版本并发控制 的缩写,它是一种在数据库管理系统中用来实现并发控制的技术。

1. MVCC 的定义

MVCC 通过为每个事务生成多个版本的数据库记录来控制并发操作。每个事务看到的是数据库的一个特定版本,而不是其他事务正在修改的数据,从而避免了锁的竞争和提高了并发性。

具体来说,MVCC 的主要特点是:

  • 每个数据行都可能有多个版本(即多个时间戳或者版本号),每个事务都可以看到自己开始时的版本。
  • 通过这种机制,数据库能够在没有加锁的情况下,保证读操作的一致性和写操作的隔离性。

2. MVCC 解决了什么问题

1. 解决了读写冲突(提高并发性)

传统的锁机制中,写操作需要加锁,这样会导致读操作阻塞,特别是当数据库写操作频繁时,很多读取操作会被锁住,导致 性能瓶颈

MVCC 允许 读取操作不加锁,从而实现了高并发的读操作,避免了因为加锁导致的读操作阻塞。读操作会看到某一时刻的数据库快照,而不受其他正在进行的写操作的影响。

举个例子:

假设有两个事务:

  • 事务 1 更新某条记录
  • 事务 2 读取该记录

如果没有 MVCC:

  • 事务 2 会因为事务 1 锁住该记录而等待。

有了 MVCC,事务 2 会看到事务 1 提交之前的版本,不会被阻塞。

2. 解决了幻读问题

幻读指的是一个事务读取数据时,另外一个事务插入或删除了满足查询条件的记录,导致该事务读取到的结果不一致。

在传统的锁机制中,事务通常只能读取快照(某时刻的数据),但是 幻读 是由于并发操作带来的不可控问题。通过 MVCC,事务 2 总是看到在事务 1 开始时刻的数据库快照,即使在事务 1 执行过程中,其他事务插入了数据,事务 2 也不会受到影响。

3. 解决了写写冲突(通过事务隔离)

在没有 MVCC 的情况下,当多个事务试图修改相同的数据时,它们之间的写冲突可能导致数据丢失或者不一致。MVCC 通过创建数据的不同版本来避免这种冲突。

当事务 A 修改数据时,它会将该数据的版本标记为 A 的版本,而事务 B 若读取该数据,则会读取到一个快照,这样它不需要等待事务 A 完成提交。因此,两个事务之间可以并行执行,解决了 并发写冲突 问题。

4. 解决了数据库的锁竞争问题

在传统的数据库系统中,当多个事务需要修改相同的数据时,需要使用锁来控制并发,这样会造成事务阻塞,严重时影响数据库性能。

MVCC 可以在 没有加锁的情况下 保证多个事务并发读写。事务 A 写入数据时,事务 B 可以并发地读取旧版本数据,不会相互干扰,从而减少了锁竞争,提高了系统的并发能力。


3. MVCC 如何实现

MVCC 主要依赖两个关键机制:

1. 版本号或时间戳

每个数据库记录都会有一个版本号(或者时间戳)。每次修改数据时,都会为该记录打上一个新的时间戳或者版本号。事务会在开始时就确定一个时间戳(如事务开始时间),然后根据该时间戳来判断读取哪些数据。

  • 当一个事务读取数据时,它看到的是 版本号小于等于它开始时的事务的版本
  • 当一个事务修改数据时,它会写入一个新的版本,这样其他事务就无法看到这个未提交的版本。

2. 隐藏删除(标记删除)

在 MVCC 中,删除操作不会立即删除数据,而是标记为“删除”或“过期”,其他事务依然可以看到这个数据,直到它提交并进行真正的清理。这样,事务仍然能够读取到之前的版本,避免了删除带来的数据丢失问题。


4. MVCC 的优缺点

优点:

  1. 提高并发性: 通过多版本控制,减少了锁竞争,使得数据库能够更高效地处理大量并发读写请求。
  2. 避免了长时间持锁: 事务不需要加锁,只需要访问自己快照中的数据,减少了锁的持有时间。
  3. 支持事务的隔离性: 每个事务都有一个一致的视图,能够在并发环境下保证数据的一致性。
  4. 解决了幻读和脏读问题: 事务始终读取自己开始时的快照数据,避免了脏读和幻读问题。

缺点:

  1. 空间开销: MVCC 会创建多个版本的数据记录,导致数据库的存储空间需求增大。
  2. 需要垃圾回收机制: 数据的版本积累需要定期清理,不然会导致存储空间的浪费。在 InnoDB 中,通常通过后台的 回收线程 定期清理过期的记录。
  3. 复杂性: MVCC 的实现较为复杂,尤其是需要处理版本管理和垃圾回收等操作。

5. MVCC 在 InnoDB 中的实现

在 InnoDB 存储引擎中,MVCC 是通过 事务 ID隐藏列(DB_TRX_ID 和 DB_ROLL_PTR) 来实现的。每个记录都包含:

  • 事务 ID:记录最后修改该记录的事务的 ID。
  • 回滚指针(DB_ROLL_PTR) :指向一个之前版本的数据。

这样,InnoDB 就能够为每个事务提供一个一致的视图,而不会受到其他并发事务的影响。


6. 背诵版

MVCC(多版本并发控制) 是一种保证数据库事务并发控制的技术,通过为每个事务提供一个数据库快照,使得每个事务能够独立读取自己开始时的数据库版本,从而避免了锁的竞争、提高了并发性。

MVCC 解决了以下问题:

  1. 提高并发性:避免了传统的加锁机制,读操作可以并行执行。
  2. 幻读问题:保证每个事务读取的是自己开始时的快照,避免了其他事务插入数据造成的数据不一致。
  3. 写写冲突:事务能够并发写入数据,通过版本控制避免了数据丢失。
  4. 锁竞争问题:减少了因为加锁造成的阻塞,提高了数据库的并发能力。

MVCC 在 InnoDB 中通过事务 ID 和回滚指针等机制来实现。