MVCC & B-Tree & 并发

MVCC & B-Tree & Concurrency

我目前正在阅读 dbms 这本书,据我所知,Mvcc(多版本并发控制)用于高并发读写事务。 但是 "concurrency control on search structures" 章节提到了 B 树的不同锁定概念(锁耦合,link 技术等)。

Mvcc不是应用在dbms中B-Tree的内部节点和叶子节点上吗? B-Tree 并发和 MVCC 完全不同吗?如果是的话,Mvvc 在 dbms 中是如何实现的?

MVCC 可以通过多种方式实现。唯一的要求是以某种方式提供旧行版本。

例如,SQL服务器将它们存储在一个临时数据库中,该数据库在服务器重新启动时被重置。

Postgres 将行版本作为隐藏行直接存储在 b 树中。它向树中添加一个隐藏键列。当从树中读取时,只公开逻辑上应该看到的版本。

RavenDB 的 Voron 将 b 树页面作为不可变数据进行管理。写入会创建全新的树。因此,MVCC 实现为从正确的不可变树中读取。

数据库很少长时间锁定物理结构。让数据库客户端停止数据库内部结构的处理不是一个好主意。内部结构通常会非常短暂地锁定。逻辑行锁单独处理。

如果我不得不猜测 concurrency control on search structures 指的是物理线程安全。这通常不涉及MVCC,因为不需要管理多个版本。普通的内存锁足以进行短暂的访问。

MVCC 意味着你不需要使用锁。

想象一下,每笔交易都有一个数字时间戳,每笔交易都会增加。在这个例子中我们有事务 1 和 2。

事务 1 读取 A 并写入值 (A + 1)。快照隔离创建事务 1 拥有的 (A) 的临时版本。 A的读取时间戳设置为事务1。

如果事务 2 同时出现并读取 A,它也将读取已提交的 A -- 它不会看到 A + 1,因为它尚未提交。事务 2 可以看到 A 的版本 == lastCommittedA 并且 <= 事务 2.

事务2在读取A的时候,也会查看A的读取时间戳,发现有事务1,检查事务1时间戳<事务2时间戳。因为 1 < 2 那么事务 2 将被中止,因为它已经依赖于 A 的旧值。

(我在 Java 中实现了 MVCC。参见 transaction, runner and mvcc code I have implemented a btree in Python。)