【问题标题】:Does mongodb transaction fail if a document read in a transaction was altered by other client before that document is altered inside the transaction?如果在事务中更改该文档之前,其他客户端更改了事务中读取的文档,则 mongodb 事务是否会失败?
【发布时间】:2022-05-27 07:54:00
【问题描述】:

在我的应用程序中,我正在使用 mongodb 进行跟踪。

  1. 启动 mongodb 会话并启动事务
  2. 阅读文档
  3. 根据文档中的值和其他一些参数进行一些计算
  4. 使用步骤 3 中的计算结果更新在步骤 2 中读取的文档
  5. 提交事务并结束会话

上述过程在TransientTransactionError上重试执行,因此如果事务由于并发问题而失败,则重试过程。

如果在上述过程中进行了两个并发调用,如果两个调用在其中任何一个写入文档之前都读取了文档,我只需要一个调用就可以成功写入文档,而另一个调用失败。如果这没有发生,我就不会得到我想要达到的预期结果。

我是否可以期望 mongodb 在这种情况下会失败一次调用,因此将在文档的更新图片上重试该过程?

【问题讨论】:

    标签: mongodb transactions


    【解决方案1】:

    MongoDB multi-document transactions 是原子的(即提供“全有或全无”的命题)。当事务提交时,事务中所做的所有数据更改都会保存并在事务外部可见。也就是说,事务在回滚其他更改时不会提交其某些更改。

    这也在In-progress Transactions and Write Conflicts中进一步阐述:

    如果事务正在进行并且在事务之外进行写入 修改事务中的操作稍后尝试的文档 要修改,事务由于写入冲突而中止。

    如果一个事务正在进行并且已经获取了一个锁来修改一个 文档,当事务外部的写入尝试修改 同一个文档,写入会一直等到事务结束。

    另请参阅写冲突部分的Video: How and When to Use Multi-Document Transactions,以更多地了解多文档事务(即写锁等)。

    【讨论】:

      【解决方案2】:

      如果您正在写入您在两个事务中读取的同一个文档,那么是的,一个会回滚。但请确保您的写入确实更改了文档,因为 MongoDB 足够聪明,如果没有任何更改,则不会更新。

      这是为了防止丢失更新。

      请看来源:https://www.mongodb.com/blog/post/how-to-select--for-update-inside-mongodb-transactions

      事实上,我在我的一个项目中有相同的实现,它按预期工作,但我有多个文档正在阅读等。但在你的具体示例中,情况并非如此。

      即使您没有事务,您也可以使用带有适当查询部分的 findAndModify(例如此处的更新操作示例:https://www.mongodb.com/docs/manual/core/write-operations-atomicity/)来保证您期望的行为。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-12-21
        • 2018-05-11
        • 1970-01-01
        • 2013-05-31
        • 1970-01-01
        • 1970-01-01
        • 2019-07-20
        相关资源
        最近更新 更多