【问题标题】:Random CursorNotFound error with MongoDBMongoDB 的随机 CursorNotFound 错误
【发布时间】:2018-11-28 17:06:24
【问题描述】:

我正在使用光标在 NodeJS 中使用 mongodb 迭代 >30k 文档,并在此迭代期间在 processFn 中写入其他文档。

示例代码:

const cursor = collection
    .find({}, { timeout: false })
    .addCursorFlag('noCursorTimeout', true);

while (await cursor.hasNext()) {
    const doc = await cursor.next();
    await processFn({ id: doc._id.toHexString(), ...doc });
}

await cursor.close();

由于未知原因,我收到随机 CursorNotFound (43) 错误。

{   MongoError: cursor id 54902755976 not found
name: 'MongoError',
message: 'cursor id 54902755976 not found',
ok: 0,
errmsg: 'cursor id 54902755976 not found',
code: 43,
codeName: 'CursorNotFound' }

at /###/node_modules/mongodb-core/lib/connection/pool.js:593:63
at authenticateStragglers (/###/node_modules/mongodb-core/lib/connection/pool.js:516:16)
at Connection.messageHandler (/###/node_modules/mongodb-core/lib/connection/pool.js:552:5)
at emitMessageHandler (/###/node_modules/mongodb-core/lib/connection/connection.js:309:10)
at Socket.<anonymous> (/###/node_modules/mongodb-core/lib/connection/connection.js:452:17)
at Socket.emit (events.js:180:13)
at addChunk (_stream_readable.js:274:12)
at readableAddChunk (_stream_readable.js:261:11)
at Socket.Readable.push (_stream_readable.js:218:10)
at TCP.onread (net.js:581:20)

我已经检查过它们不是超时。它们总是在不到 5 分钟后发生。另外cursor.metrics 表示只有一个游标打开并且这个游标启用了noCursorTimeout

我还检查了processFn 是否正确解析。

我阅读了有关会话和连接超时的信息,并将它们增加到极高的数量以进行测试。还是没有变化。

还有什么原因以及如何调试此错误?

【问题讨论】:

    标签: node.js mongodb


    【解决方案1】:

    我正在研究同样的错误并遇到了这个:

    https://jira.mongodb.org/browse/SERVER-34810

    这似乎是一个服务器问题,需要将 mongo 至少升级到 3.6.6、4.0.1 或 4.1.1。

    或者非常小的批量大小(~20)似乎在一定程度上缓解了这个问题。

    【讨论】:

    • 感谢您的回答! :) 这可能确实是原因。我会检查一下。
    【解决方案2】:

    我建议你使用find 方法,你可以将一个对象作为第二个参数传递给接收timeout 属性,它会防止光标超时。

    collection.find({}, { timeout: false })
    

    文档:http://mongodb.github.io/node-mongodb-native/3.6/api/Collection.html#find

    【讨论】:

      【解决方案3】:

      最新(2021 年)答案:

      • 创建会话,然后关联所有操作与该会话
      • 然后定期刷新会话

      -> 官方演示代码

      var session = db.getMongo().startSession()
      var sessionId = session.getSessionId().id
      
      var cursor = session.getDatabase("examples").getCollection("data").find().noCursorTimeout()
      var refreshTimestamp = new Date() // take note of time at operation start
      
      while (cursor.hasNext()) {
      
        // Check if more than 5 minutes have passed since the last refresh
        if ( (new Date()-refreshTimestamp)/1000 > 300 ) {
          print("refreshing session")
          db.adminCommand({"refreshSessions" : [sessionId]})
          refreshTimestamp = new Date()
        }
      
        // process cursor normally
      
      }
      

      ->更多细节可以参考another post answer

      【讨论】:

        猜你喜欢
        • 2019-01-02
        • 2016-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-02
        • 2013-01-26
        • 1970-01-01
        相关资源
        最近更新 更多