CockroachDB 两阶段提交有或没有阻塞?

CockroachDB 2-phase commits with or without blocking?

两阶段提交应该会遇到阻塞问题。 CockroachDB 是否就是这种情况,如果不是,如何避免?

CockroachDB 有一篇很长的博客 post 关于它如何在不锁定的情况下使用两阶段提交:https://www.cockroachlabs.com/blog/how-cockroachdb-distributes-atomic-transactions/

关于防止锁定处理最多的部分是它对 "write intents" 的使用(Stage: Write Intents 是博客中的标题 post ).

总结:两阶段提交是阻塞的,因此尽可能保持两阶段提交的内容尽可能 "small" 很重要,这样被阻止的所有操作的集合是最小的。 CockroachDB 使用具有 intents 的 MVCC 来做到这一点,两阶段仅在一个意图上提交。因为 CockroachDB 提供 可序列化 事务,它会重新排序事务时间戳,以最大限度地减少阻塞,只在绝对必要的地方。

更长的答案

2-phase commits 在第一阶段之后处于阻塞状态,而所有参与者都在等待 协调器 对第二阶段是要提交还是中止的回复。在此期间,已经发送 "Yes" 投票的参与者不能单方面撤销他们的投票,也不能将其视为已提交(因为协调者可能会中止)。因此,他们被迫阻止所有需要具体了解此交易状态的后续操作。上面这句话的关键在于“需要”:我们有责任设计我们的系统以将这个集合减少到最低限度。 CockroachDB 使用 write intents[MVCC] 来最小化这些依赖性。

考虑分布式(多键)事务性键值存储的简单实现:我希望事务性地提交一些写事务 t1t1 跨越多台机器的许多键,但特别值得关注的是它写入 k1 = v2k1 在机器 m1 上(假设 k1=v1 是之前的值)。

由于t1跨越许多机器上的许多键,所有这些键都涉及到一个两阶段提交事务。一旦 2-phase 交易开始,我们必须注意我们有一个写 k1=v2 的意图,并且交易的状态是未知的(交易可能会中止,因为 other 之一 写入无法继续)。

现在,如果出现其他交易 t2 想要读取 k1 的值,我们根本无法为该交易提供权威答案,直到我们知道 2- 的最终结果阶段提交。 t2 被屏蔽了。

但是,我们(和 CockroachDB)可以做得更好。我们可以为每个键保留 多个版本 值,并有一个 并发控制 机制来保持所有这些版本的顺序。即,我们可以分配我们的交易 时间戳 ,并让我们的写入看起来(松散地)如下:

`k1 = v1 committed at time=1`
`k1 = v2 at time=110 INTENT (pending transaction t1)`

现在,当 t2 出现时,它有一个选项:它可以选择在 time<=109 处进行读取,而不会在 t1 处被阻止。当然,有些交易不能这样做(如果说,它们也是分布式的,并且有一个不同的组件只需要更高的时间戳)。这些交易将被阻止。但在实践中,这释放了数据库来分配时间戳,以便可以进行许多类型的事务。

正如另一个答案所说,Cockroach Labs post 关于 CockroachDB 对 MVCC here 的使用,其中还解释了一些进一步的细节。