在Node.js中防止与数据库相关的竞争条件 [英] Preventing database-related race conditions in Node.js

查看:84
本文介绍了在Node.js中防止与数据库相关的竞争条件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am attempting to understand how to ensure aynchronous safety when using an instance of a model when using Node.js. Here, I use the Mongoose ODM in code samples, but the question applies to any case where a database is used with the asynchronous event-driven I/O approach that Node.js employs.

考虑以下代码(它将Mongoose用于MongoDB查询):

Consider the following code (which uses Mongoose for MongoDB queries):

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描述的文档.考虑以下代码:

In a separate part of the application, the document described by MyModel could be updated. Consider the following code:

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

在代码段A中,MongoDB查询与已注册的回调一起发出,一旦文档准备就绪,将触发该查询. MyModel描述的文档的实例保留在内存中(在"doc"对象中).可能会发生以下顺序:

In Snippet A, a MongoDB query is issued with a registered callback to be fired once the document is ready. An instance of the document described by MyModel is retained in memory (in the "doc" object). The following sequence could occur:

  1. 代码段A 执行
  2. 启动针对MyModel的查询,注册一个回调(回调A)以供以后使用
  3. << Node事件循环运行>>
  4. 从数据库中检索MyModel,执行注册的回调(回调A)
  5. 针对MyOtherModel发起查询,注册一个回调以供以后使用(回调B)
  6. << Node事件循环运行>>
  7. 代码段B 执行
  8. 文档(编号1)已更新
  9. << Node事件循环运行>>
  10. 从数据库中检索MyOtherModel,执行已注册的回调(回调B)
  11. 比较中错误地使用了过时的文档版本(id#1).
  1. Snippet A executes
  2. A query is initiated for MyModel, registering a callback (callback A) for later use
  3. << The Node event loop runs >>
  4. MyModel is retrieved from the database, executing the registered callback (callback A)
  5. A query is initiated for MyOtherModel, registering a callback for later use (callback B)
  6. << The Node event loop runs >>
  7. Snippet B executes
  8. The document (id #1) is updated
  9. << The Node event loop runs >>
  10. MyOtherModel is retrieved from the database, executing the registered callback (callback B)
  11. The stale version of the document (id #1) is incorrectly used in a comparison.

问题

  1. 是否可以保证在Node.js/MongoDB中不会发生这种竞争情况?
  2. 如何确定性地防止这种情况的发生?

虽然Node以单线程方式运行代码,但在我看来,事件循环的任何运行都为潜在的过时数据打开了大门.如果遵守错误,请纠正我.

While Node runs code in a single-threaded manner, it seems to me that any allowance of the event loop to run opens the door for potentially stale data. Please correct me if this observance is wrong.

推荐答案

不,不能保证在node.js/MongoDB中不会发生这种竞争情况.不过,它与node.js无关,而且对于支持并发访问的任何数据库(不仅仅是MongoDB),这都是可能的.

No, there are no guarantees that this type of race condition won't occur in node.js/MongoDB. It doesn't have anything to do with node.js though, and this is possible with any database that supports concurrent access, not just MongoDB.

但是,问题是使用MongoDB解决起来比较棘手,因为它不像典型的SQL数据库那样支持事务.因此,您必须使用MongoDB食谱这里.

The problem is, however, trickier to solve with MongoDB because it doesn't support transactions like your typical SQL database would. So you have to solve it in your application layer using a strategy like the one outlined in the MongoDB cookbook here.

这篇关于在Node.js中防止与数据库相关的竞争条件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆