【问题标题】:Two phase commit in MongoDBMongoDB 中的两阶段提交
【发布时间】:2013-11-08 04:34:07
【问题描述】:

仔细阅读the online documentation,我对MongoDB中的两阶段提交仍有很多疑问。

从故障场景中恢复部分,为什么只有两类故障?在我看来,这些步骤中的任何一个都可能发生失败,所以这里应该有两个以上的类。例如,如果(在 Apply Transaction to Both Accounts 部分),在更新帐户 A 后数据库服务器失败了怎么办。这意味着账户 A 损失了一些钱,而账户 B 没有发生任何事情。我们会有不一致的交易吗?

【问题讨论】:

    标签: mongodb transactions


    【解决方案1】:

    当应用程序或数据库在将事务应用到 A 和将事务应用到 B 之间突然崩溃时,全局事务集合中仍然会有 state:"pending" 的事务。您在崩溃后运行的恢复脚本应该注意到这一点,检查两个帐户,并查看其中一个帐户中存在待处理事务,但另一个帐户中没有。它现在知道回滚事务或尝试完成事务所需的一切。

    是的,编写一个如此智能的恢复脚本并不容易。但是在不是为他们设计的数据库系统中的事务总是很难的。有时,您可以通过将需要一起更新的字段始终在同一个文档中的方式设计文档来解决在 MongoDB 中需要事务的问题,但并不总是有一种明智的方法来做到这一点。当您的用例绝对需要事务时,请保护您的理智并使用关系数据库。

    【讨论】:

    • 只是对最后一点的注释。有非关系数据库支持事务,所以你不必使用关系数据库来保持理智:)
    【解决方案2】:

    在我看来,这些步骤中的任何一步都可能发生失败,所以这里应该有两个以上的类。

    这里要记住的关键是文档不是关于两阶段提交的权威指南,实际上两阶段提交在 MongoDB 中技术上是不可能的,如果你想执行它们,我强烈建议你获得 ACID 技术。

    您必须记住,由于不在服务器本身内,您无法应对某些失败情况。相反,两阶段提交的整个存在只是客户端,因此与 TTL 监控相比,它非常脆弱。

    更新帐户 A 后,数据库服务器出现故障。这意味着账户 A 损失了一些钱,而账户 B 没有发生任何事情。我们会有不一致的交易吗?

    为了支持 Philipps 的回答,在这种情况下,账户 A 和 B 之间的原始交易仍处于待处理状态,只有在账户 B 更新后才会将其移至完成/完成。

    这意味着交易在完成之前不能被标记为已完成。

    我建议使用专为您的场景设计的东西,而不是将 MongoDB 用于并非真正设计的场景。

    【讨论】:

    • 为什么多次说 MongoDB 不能真正实现两阶段提交并谈论 ACID ?您应该对作为您答案的一部分的正确答案感到满意。 MongoDB 确实可以支持真正的 2 阶段提交,这要归功于您使用事务标记已修改文档(这里是帐户)的能力。所有恢复方案都可以在这里实现。
    • @rpechayr MongoDB 不持有事务锁,MongoDB 并发的基本原理打破了 ACID 范式。它可以支持允许回滚但没有跨所有分片的全局锁定的操作,您会发现这些操作仍然容易出现许多问题,TokuMX 使用全局锁定来实现其事务
    • @rpechayr 我在哪里说支持 2 阶段提交?很高兴知道文档中提到的 2 阶段提交并不是 ACID 数据库中真正发生的事情
    • 我很想知道这些可能发生的许多问题。 MongoDB 中两阶段提交的有趣之处在于,它使人们能够实现最终一致的事务而不需要需要全局锁,而全局锁无法扩展。
    • @rpechayr 我认为最大的问题是这种一致性是在客户端提供的,它不是在 mongodb 本身中以任何方式、形状或形式提供的。这提供了足够的问题。此外,在多个文档的 MongoDB“事务”期间,文档可以被修改和过期。因此,在两阶段提交中,您不能总是说您正在更新正确的文档。
    【解决方案3】:

    在线文档可能并不完美。 实际上,您确实需要回滚 A 和 B 上的操作

    【讨论】:

      猜你喜欢
      • 2011-11-15
      • 2019-04-13
      • 1970-01-01
      • 1970-01-01
      • 2011-11-24
      • 2013-05-21
      • 1970-01-01
      • 2015-02-02
      相关资源
      最近更新 更多