防止并发访问 Mongoose 中的文档

Zxi*_*fer 4 mongoose mongodb node.js

我的服务器应用程序(使用 node.js、mongodb、mongoose)有一个文档集合,重要的是两个客户端应用程序不能在没有看到彼此修改的情况下同时修改它们。

为了防止这种情况,我添加了一个简单的文档版本控制系统:模式上的一个预挂钩,用于检查文档的版本是否有效(即,不高于客户端上次读取的版本)。乍一看,它工作正常:

// Validate version number
UserSchema.pre("save", function(next) {
  var user = this

  user.constructor.findById(user._id, function(err, userCurrent) { // userCurrent is the user that is currently in the db
    if (err) return next(err)
    if (userCurrent == null) return next()

    if(userCurrent.docVersion > user.docVersion) {
      return next(new Error("document was modified by someone else"))
    } else {
      user.docVersion = user.docVersion + 1
      return next()
    }
  })
})
Run Code Online (Sandbox Code Playgroud)

问题如下:

当两个客户端应用程序同时保存一个用户文档时,这些是否可能在预挂钩和实际保存操作之间交错?我的意思是,想象一下时间从左到右,v 是版本号(由保存保存):

App1:  findById(pre)[v:1]                                   save[v->2]
App2:                      findById(pre)[v:1]   save[v->2]
Run Code Online (Sandbox Code Playgroud)

导致 App1 保存了同时(由 App2)修改过的东西,它没有办法注意到它被修改了。App2的更新完全丢失。

我的问题可能归结为:Mongoose pre-hook 和 save 方法是否在一个原子步骤中发生?

如果没有,你能给我一个关于如何解决这个问题的建议,这样就不会丢失任何更新吗?

谢谢!

rob*_*lep 5

findAndModify对于单个匹配文档,MongoDB 具有原子操作。

Mongoose 有多种使用此方法的方法,我认为它们将适合您的用例:

另一种解决方案(Mongoose 本身也用于其自己的文档版本控制)是使用Update Document if Current模式。