两阶段提交应该受阻塞问题的影响。这是CockroachDB的情况,如果没有,它是如何避免的?
答案 0 :(得分:4)
摘要:两阶段提交是阻塞的,因此将两阶段提交的事物保持为“尽可能小”非常重要,以便所有操作的集合都是被阻止是最小的。 CockroachDB使用带有意图的MVCC进行此操作,仅针对单个意图进行2阶段提交。由于CockroachDB提供了可序列化的事务,因此它会重新排序事务时间戳,以便仅在绝对必要的情况下最小化阻塞。
2-phase commits在第一阶段后被阻止,而所有参与者都在等待协调员的回复,询问是否要提交或中止第二阶段。在此期间,已经发出“是”投票的参与者不能单方面撤销他们的投票,但也不能将其视为已提交(因为协调员可能会以中止的方式取回)。因此,他们被迫阻止所有后续行动,这些行动需要具体了解此交易的状态。上面句子中的关键是“ need ”:我们设计我们的系统以将该设置减少到最低限度。 CockroachDB使用写入意图和 [MVCC] 来最小化这些依赖关系。
考虑一个分布式(多键)事务键值存储的简单实现:我希望以事务方式提交一些写事务t1
。 t1
涵盖了许多计算机上的许多密钥,但特别值得关注的是它写入k1 = v2
。 k1
位于计算机m1
上(假设k1=v1
是之前的值)。
由于t1
跨越许多机器上的许多密钥,因此所有这些密钥都涉及两阶段提交事务。一旦开始这个两阶段交易,我们必须注意到我们有意写k1=v2
,并且事务的状态是未知的(事务可能会中止,因为其中一个其他写入无法继续)。
现在,如果有其他事务t2
出现,想要读取k1
的值,我们就无法给该事务一个权威的答案,直到我们知道两阶段提交的最终结果为止。 t2
已被屏蔽。
但是,我们(和CockroachDB)可以做得更好。我们可以为每个密钥保留多个版本的值,并具有并发控制机制,以便按顺序保留所有这些版本。也就是说,我们可以分配我们的交易 timestamps ,并让我们的写作(松散地)看起来如下:
`k1 = v1 committed at time=1`
`k1 = v2 at time=110 INTENT (pending transaction t1)`
现在,当t2
出现时,它有一个选项:它可以选择time<=109
处的阅读,这不会在t1
上被阻止。当然,有些交易不能这样做(如果说它们也是分布式的,并且有一个不同的组件只需要更高的时间戳)。这些交易将被阻止。但实际上,这会释放数据库以分配时间戳,以便可以继续进行多种类型的事务。
正如另一个答案所说,Cockroach Labs有一篇关于CockroachDB使用MVCC here的文章,该文章还解释了一些进一步的细节。
答案 1 :(得分:1)
CockroachDB有一篇很长的博客文章,介绍了如何在不锁定的情况下使用两阶段提交:https://www.cockroachlabs.com/blog/how-cockroachdb-distributes-atomic-transactions/
最能防止锁定的部分是使用&#34;写入意图&#34; (阶段:写入意图是博客文章中的标题)。