一尘不染

Node.js / Mongoose上的“ VersionError:找不到匹配的文档”错误

node.js

我对Node.js和Mongo / Mongoose相对较新,并且在排查特定Mongoose错误时遇到了 非常 困难的时间:

VersionError:找不到匹配的文档。

(此问题底部的整个错误跟踪/堆栈。)

这篇博客非常清楚地概述了VersionError可能如何发生:

(TL; DR-“ Mongoose
v3现在向每个文档添加了可配置模式的版本密钥。只要对数组的修改有可能更改任何数组元素的位置,此值都会自动增加。”如果您尝试保存文档,但是版本键不再与您检索到的对象匹配,您将获得上述内容VersionError。)

核心问题: 有什么方法可以显示违规save()操作?还是哪个文档保存失败?还是 什么 ?;)

挑战: 这是一个包含许多数组的相对较大的代码库,我不确定如何开始对问题进行故障排除。特别是,错误跟踪/堆栈似乎无法显示问题所在。见下文:

VersionError: No matching document found.
at handleSave (<project_path>/node_modules/mongoose/lib/model.js:121:23)
at exports.tick (<project_path>/node_modules/mongoose/lib/utils.js:408:16)
at null.<anonymous> (<project_path>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection.js:484:9)
at g (events.js:192:14)
at EventEmitter.emit (events.js:126:20)
at Server.Base._callHandler (<project_path>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/base.js:391:25)
at Server.connect.connectionPool.on.server._serverState (<project_path>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:558:20)
at MongoReply.parseBody (<project_path>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js:131:5)
at Server.connect.connectionPool.on.server._serverState (<project_path>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:517:22)
at EventEmitter.emit (events.js:96:17)

阅读 250

收藏
2020-07-07

共1个答案

一尘不染

根据请求,以下是我们的问题及其解决方案的概述:

在我们的系统中,我们创建了一个自定义文档锁定例程(使用redis-lock),其中以下操作以这种精确(不正确)的顺序发生:

操作顺序不正确:

  1. 收到客户要求
  2. 文件已锁定
  3. 检索文件
  4. 文件已编辑
  5. 文件已解锁
  6. 客户要求已解决
  7. 文件已储存

一旦看到它写出来,问题就很明显了:我们将文档保存在文档锁之外。

假设#6在我们的系统中花费了100ms。这是一个100毫秒的窗口,如果任何其他请求都抓住了该文档,我们将发生保存冲突(此问题中的标题错误基本上是保存冲突恕我直言)。

换句话说,在我们的系统中,请求A抓取了文档X的版本1,对其进行了编辑,然后将其解锁,但是在请求A保存该文档之前,请求B抓取了文档X并将其递增到版本2(在Mongo上阅读)有关更多信息的版本)。然后,请求A解析其客户请求并保存文档X,但它正在尝试保存版本1,现在它看到它具有版本2,因此出现上述错误。

因此修复很容易。将文档保存在锁中。(在上面的示例中,将#7移至#5之前。请参见下文。)

正确/固定的操作顺序

  1. 收到客户要求
  2. 文件已锁定
  3. 检索文件
  4. 文件已编辑
  5. 文件已储存
  6. 文件已解锁
  7. 客户要求已解决

(您可以争辩说应该交换#6和#7,但这不在Mongo / Mongoose /这个问题的范围内。)

我将暂时搁置这个问题,看看是否有人可以找到更好的方法来隔离相关代码并解决此问题。在我们的案例中,这是一个非常系统的问题,非常难以解决当时的技术水平。

2020-07-07