【问题标题】:Preventing database-related race conditions in Node.js在 Node.js 中防止与数据库相关的竞争条件
【发布时间】:2012-10-22 20:32:01
【问题描述】:

概述

我试图了解在使用 Node.js 时使用模型实例时如何确保异步安全。在这里,我在代码示例中使用了 Mongoose ODM,但这个问题适用于将数据库与 Node.js 采用的异步事件驱动 I/O 方法一起使用的任何情况。

考虑以下代码(使用 Mongoose 进行 MongoDB 查询):

片段 A

MyModel.findOne( { _id : <id #1> }, function( err, doc ) {
    MyOtherModel.findOne( { _id : someOtherId }, ( function(err, otherDoc ) {
        if (doc.field1 === otherDoc.otherField) {
            doc.field2 = 0; // assign some new value to a field on the model
        }
        doc.save( function() { console.log( 'success' ); }
    });
});

在应用程序的单独部分中,可以更新由 MyModel 描述的文档。考虑以下代码:

片段 B

MyModel.update( { _id : <id #1> }, { $set : { field1 : someValue }, callback );

在 Snippet A 中,发出一个 MongoDB 查询,并在文档准备好后触发一个已注册的回调。 MyModel 描述的文档实例保留在内存中(在“doc”对象中)。可能会出现以下顺序:

  1. 片段 A 执行
  2. 为 MyModel 发起查询,注册回调(回调 A)供以后使用
  3. >
  4. 从数据库中检索MyModel,执行注册的回调(回调A)
  5. 为 MyOtherModel 发起查询,注册回调以供以后使用(回调 B)
  6. >
  7. 片段 B 执行
  8. 文档 (id #1) 已更新
  9. >
  10. 从数据库中检索MyOtherModel,执行注册的回调(回调B)
  11. 在比较中错误地使用了文档的旧版本(id #1)。

问题

  1. 是否有任何保证不会在 Node.js/MongoDB 中发生这种类型的竞争条件?
  2. 我可以做些什么来确定性地防止这种情况发生?

虽然 Node 以单线程方式运行代码,但在我看来,任何允许运行事件循环的行为都会为潜在的陈旧数据打开大门。如果这种遵守方式有误,请纠正我。

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    不,不能保证这种类型的竞争条件不会在 node.js/MongoDB 中发生。不过它与 node.js 没有任何关系,这对于任何支持并发访问的数据库都是可能的,而不仅仅是 MongoDB。

    然而,使用 MongoDB 解决这个问题比较棘手,因为它不像典型的 SQL 数据库那样支持事务。因此,您必须使用 MongoDB 食谱here 中概述的策略在应用程序层中解决它。

    【讨论】:

      猜你喜欢
      • 2019-02-23
      • 1970-01-01
      • 2011-09-22
      • 1970-01-01
      • 2017-07-24
      • 2016-03-21
      • 2013-03-11
      • 2012-04-08
      • 1970-01-01
      相关资源
      最近更新 更多