使用Mongoose处理MongoDB中查找,修改和保存流程时的冲突

时间:2014-07-17 16:06:15

标签: node.js mongodb mongoose

我想更新一个涉及阅读其他集合和复杂修改的文档,因此findAndModify()中的更新操作符无法满足我的目的。

以下是我所拥有的:

Collection.findById(id, function (err, doc) {

    // read from other collection, validation
    // modify fields in doc according to user input
    // (with decent amount of logic)

    doc.save(function (err, doc) {
      if (err) {
        return res.json(500, { message: err });
      }

      return res.json(200, doc);
    });
}

我担心如果多个客户端碰巧修改同一文档,此流程可能会导致冲突 据说here

  

使用MongoDB数据库对单个文档的操作始终是原子的

我对Operations的含义感到有点困惑。

  • 这是否意味着findById()将获取锁定,直到doc超出范围(发送响应之后),因此不会发生冲突? (我不这么认为)
  • 如果没有,如何修改我的代码以支持多个客户知道他们将修改Collection?
  • Mongoose会报告发生冲突吗?
  • 如何处理可能发生的冲突?是否可以手动锁定集合?
    • 我看到建议使用Mongoose的versionKey(或时间戳)并重试过时的文档
    • 完全没有使用MongoDB ......

感谢。


修改

感谢@jibsales指针,我现在使用Mongoose的versionKey(时间戳也可以),以避免发生冲突。

aaronheckmann — Mongoose v3 part 1 :: Versioning

请参阅此示例代码:
https://gist.github.com/anonymous/9dc837b1ef2831c97fe8

2 个答案:

答案 0 :(得分:3)

操作是指读/写。请记住,MongoDB不是符合ACID标准的数据层,如果您需要真正的ACID合规性,那么最好选择其他技术。也就是说,您可以通过两阶段提交技术outlined in this article in the MongoDB docs实现原子性和隔离。这不是一件小事,所以要为一些繁重的工作做好准备,因为你需要与本地驱动程序而不是Mongoose一起工作。同样,我的最终建议是,如果您需要交易支持,请不要喝NoSQL koolaid。听起来就是这样。

答案 1 :(得分:1)

当MongoDB收到更新文档的请求时,它将锁定数据库,直到它完成操作。 MongoDB收到的任何其他请求将等待锁定操作完成并且数据库已解锁。此锁定/等待行为是自动的,因此不需要处理任何冲突。您可以在常见问题解答的Concurrency部分找到有关此行为的更多信息。

有关进行多文档事务的MongoDB推荐技术的链接,请参阅jibsales答案。

有几个NoSQL数据库可以进行完整的ACID交易,这将使您的生活更加轻松。 FoundationDB就是这样一个数据库。数据存储为键值,但它通过图层支持多个数据模型。

完全披露:我是FoundationDB的工程师。