我遇到了一种情况,我开始怀疑两阶段提交协议是否确实保证了ACID属性,特别是它的'A'部分。
让我们看一下涉及2个资源的理论分布式事务。 (更多关于我必须处理的问题的实际描述可以在my blog中找到)。该场景是分布式事务的正常执行(无故障或恢复)。应用程序启动事务,更新两个资源并发出commit()调用。提交完成后,应用程序将检查两个资源并查看已完成事务的所有更改。一切都很好,2PC协议完成了它的工作,对吗?
现在,对场景进行了一些小改动。当分布式事务正在执行commit()时,另一个应用程序将使用相同的2个资源。它只能看到交易的部分变化吗?假设,对第二个资源的更改尚未显示时,对一个资源的更改已经可见了吗?
在我阅读过2PC协议的所有信息中,我找不到任何关于各个资源相对于彼此的变化可见性的保证。而且我找不到任何说明所有资源在同一时间完成各自提交的内容。
答案 0 :(得分:6)
我认为你的主题令人困惑。 2PC确保事务提交具有一定的可见性。即在您的事务中,您提交的数据将以特定方式进行排序,并提交该事务将按顺序提交。
在事务之外,您看到的行为将取决于锁定在数据库中的工作方式。通常,您会期望只读查询可以看到事务前状态或事务后事务状态(除非它使用相同的锁定语义,否则不会保证它接收到哪个状态)。写语义通常会导致锁定事务中的所有项,但这又取决于数据库的配置方式。
2PC实际上只承诺一个操作是Atomic,即使这样,它也只是该事务范围内的原子,具体取决于数据库的配置方式。
答案 1 :(得分:4)
我认为你将2PC与concurrency control混淆了。两阶段提交可确保事务中的所有参与线程都提交或中止。并发控制可确保在相同或单独的应用程序中进行某种事务排序。根据您的要求,有多种方法可以处理,但完全序列化的交易肯定是可能的。
答案 2 :(得分:2)
The article明确指出2PC 对所有可能的故障配置都不具备弹性。这里更具体的参考:Three phase commit protocol:
最近,Dale Skeen和Michael Stonebraker在他们的论文“分布式系统中的崩溃恢复的正式模型”中描述了3PC。[1]在这项工作中,他们将2PC建模为非确定性有限状态自动机系统,并证明它对随机单站点故障不具有弹性。
编辑:这可用于破坏所有4个 ACID 属性。我的初步答案是错误的。
是一个正交问题,取决于所涉及的群组配置(参见Isolation levels)。
问题的主体和blog是关于隔离,而不是原子性。原子性意味着事务总是结束,最终提交所有更改(或全部回滚)。
即使所有同类群组都是 Serializable 并使用相同的TransactionManager,我仍然可以通过在合适的时间启动新交易来避免隔离。
在研究了您的博客后,我会说,两阶段提交协议无法解决您的问题,必须更有创意地重新设计MDB通信。
由于阻塞特性, 2PC 几乎在任何实际情况下都是过度杀伤,明智的存储位置和数据流设计可以提供更好的解决方案。基本上,您需要唯一最权威的任何类型的信息来源,所有其他相关方必须能够将自己更新为该权威状态。 http://en.wikipedia.org/wiki/Communicating_sequential_processes是一个很好的灵感,特别是在Go中实现的。现代分布式数据库 BASE 而不是 ACID (http://en.wikipedia.org/wiki/Eventual_consistency)。