16

我遇到了一种情况,我开始怀疑两阶段提交协议是否真的保证了 ACID 属性,尤其是它的“A”部分。

让我们看一个涉及 2 个资源的理论分布式事务。(关于我必须处理的问题的更实际描述可以在我的博客中找到)。该场景是分布式事务的正常执行(无故障或恢复)。应用程序启动事务,更新资源并发出 commit() 调用。提交完成后,应用程序检查两个资源并查看已完成事务的所有更改。一切都很好,2PC 协议完成了它的工作,对吧?

现在,对场景进行一个小改动。当分布式事务执行 commit() 时,另一个应用程序将访问相同的 2 个资源。它只能看到交易的部分变化吗?比方说,对一个资源的更改已经可见,而对第二个资源的更改尚不可见?

在我阅读的有关 2PC 协议的所有信息中,我找不到任何关于各个资源相对于彼此的变化的可见性的保证。而且我找不到任何说所有资源都在完全相同的时间完成它们的个人提交的东西。

4

3 回答 3

11

我认为您在混淆主题。2PC 确保事务提交具有一定的可见性。即在您的事务中,您提交的数据将以特定方式排序,并且与该事务一起提交的数据将按顺序提交。

在事务之外,您看到的行为将取决于锁定在数据库中的工作方式。通常,您会期望只读查询会看到之前的事务状态或之后的事务状态(除非它使用相同的锁定语义,否则不能保证它接收到的本身)。写语义通常会导致锁定事务中的所有项目,但这同样取决于您的数据库的配置方式。

2PC 实际上只承诺一个操作是原子的,即使这样,它也只是在该事务的范围内必须是原子的,具体取决于您的数据库的配置方式。

于 2014-05-08T22:27:35.607 回答
5

I think you're confusing 2PC with concurrency control. Two-phase commit ensures that all the participating threads in a transaction either commit or abort. Concurrency control ensures some sort of ordering of transactions in the same or separate applications. There are various ways of handling this depending on your requirements, but fully serialized transactions are certainly possible.

于 2011-01-09T14:53:50.237 回答
2

来自维基百科

文章一开始就明确指出 2PC 不能适应所有可能的故障配置。更具体的参考这里:三阶段提交协议

3PC 最初由 Dale Skeen 和 Michael Stonebraker 在他们的论文“分布式系统中的崩溃恢复的正式模型”中描述。 [1] 在这项工作中,他们将 2PC 建模为非确定性有限状态自动机系统,并证明它对随机单站点故障没有弹性。

编辑:这可用于破坏所有 4 个ACID属性。我最初的回答是错误的。

变化的可见性

是一个正交问题,取决于所涉及的群组配置(请参阅隔离级别)。

您的问题和博客的主体是关于隔离,而不是原子性。原子性意味着事务始终完成到最后,最终提交所有更改(或全部回滚)。

即使所有群组都是可序列化的并使用相同的 TransactionManager,我仍然看到通过在正确的时间启动新事务来规避隔离的可能性。

在研究了你的博客之后,我想说两阶段提交协议不能解决你的问题,必须更有创意地重新设计 MDB 通信。

从个人经验

由于阻塞的性质,2PC在几乎任何实际情况下都是过大的,存储位置和数据流的明智设计可以提供更好的解决方案。基本上,您需要任何类型信息的唯一最权威来源,并且所有其他相关方必须能够将自己更新到该权威状态。http://en.wikipedia.org/wiki/Communicating_sequential_processes是一个很好的灵感,尤其是在Go中实现的。现代分布式数据库是BASE而不是ACID ( http://en.wikipedia.org/wiki/Eventual_consistency )。

于 2014-05-10T12:58:41.303 回答