【问题标题】:MongoDB CursorNotFound Error on collection.find() for a few hundred small recordsMongoDB CursorNotFound 数百条小记录的 collection.find() 错误
【发布时间】:2019-01-02 17:35:17
【问题描述】:

我正在使用本机 Node JS 驱动程序 (v. 3.0.10) 在 Mongo 3.6.6(在小型 Mongo Atlas 集群上,未分片)上运行

我的代码如下所示:

const records = await collection.find({
  userId: ObjectId(userId),
  status: 'completed',
  lastUpdated: {
    $exists: true,
    $gte: '2018-06-10T21:24:12.000Z'
  }
}).toArray();

我偶尔会看到此错误:

{
  "name": "MongoError",
  "message": "cursor id 16621292331349 not found",
  "ok": 0,
  "errmsg": "cursor id 16621292331349 not found",
  "code": 43,
  "codeName": "CursorNotFound",
  "operationTime": "6581469650867978275",
  "$clusterTime": {
    "clusterTime": "6581469650867978275",
    "signature": {
      "hash": "aWuGeAxOib4XWr1AOoowQL8yBmQ=",
      "keyId": "6547661618229018626"
    }
  }
}

最多返回几百条记录的查询会发生这种情况。每条记录有几百个字节。

我在网上查找了可能是什么问题,但what 中的mostfound 正在谈论需要超过 10 分钟才能完成的非常大的操作的游标超时。我无法从我的日志中准确判断失败的查询花费了多长时间,但最多只有两秒(可能比这短得多)。

我测试了使用与出错的查询相同的值运行查询,explain 的执行时间仅为几毫秒:

"executionStats" : {
    "executionSuccess" : true, 
    "nReturned" : NumberInt(248), 
    "executionTimeMillis" : NumberInt(3), 
    "totalKeysExamined" : NumberInt(741), 
    "totalDocsExamined" : NumberInt(741), 
    "executionStages" : {...}
    }, 
    "allPlansExecution" : []
    ]
} 

有什么想法吗?间歇性网络延迟会导致此错误吗?我将如何减轻这种情况?谢谢

【问题讨论】:

  • 你在用猫鼬吗?
  • 不,不使用猫鼬
  • 请注意,如果您使用的是 Atlas,您可以单击左侧的 Support 按钮查看问题。您使用的是哪个 Atlas 层?
  • 您是否尝试过从本地计算机 ping 主节点主机名?也许是网络。
  • 有些人遇到这种情况是因为节点进程不堪重负,无法全部及时服务。 jira.mongodb.org/browse/NODE-844。还有要检查的东西

标签: node.js mongodb


【解决方案1】:

你可以试试这 3 件事:


a)Set the cursor to false

db.collection.find().noCursorTimeout();

你必须在某个点用 cursor.close(); 关闭光标


b)Or reduce the batch size

db.inventory.find().batchSize(10);

c) 游标过期时重试:

let processed = 0;
let updated = 0;

while(true) {
    const cursor = db.snapshots.find().sort({ _id: 1 }).skip(processed);

    try {
        while (cursor.hasNext()) {
            const doc = cursor.next();

            ++processed;

            if (doc.stream && doc.roundedDate && !doc.sid) {
                db.snapshots.update({
                    _id: doc._id
                }, { $set: {
                    sid: `${ doc.stream.valueOf() }-${ doc.roundedDate }`
                }});

                ++updated;
            } 
        }

        break; // Done processing all, exit outer loop
    } catch (err) {
        if (err.code !== 43) {
            // Something else than a timeout went wrong. Abort loop.

            throw err;
        }
    }
}

【讨论】:

  • @RandyLam 很高兴我的回答对您有所帮助;)
【解决方案2】:

首先,如果您的数据太大,使用 toArray() 方法不是一个好主意,而是最好使用 forEach() 并循环抛出数据。 就像这样:

const records = await collection.find({
  userId: ObjectId(userId),
  status: 'completed',
  lastUpdated: {
    $exists: true,
    $gte: '2018-06-10T21:24:12.000Z'
  }
});

records.forEach((record) => {
    //do somthing ...
});

其次,您可以使用 {allowDiskUse: true} 选项来获取大数据。

const records = await collection.find({
  userId: ObjectId(userId),
  status: 'completed',
  lastUpdated: {
    $exists: true,
    $gte: '2018-06-10T21:24:12.000Z'
  }
},
{allowDiskUse: true});

【讨论】:

    猜你喜欢
    • 2018-11-28
    • 2016-11-16
    • 1970-01-01
    • 2016-03-06
    • 1970-01-01
    • 1970-01-01
    • 2019-09-16
    • 1970-01-01
    • 2023-01-31
    相关资源
    最近更新 更多