提问者:小点点

长时间运行的查询循环中的mongo MongoCursorNotFoundException


我有一个简单的查询循环,它在大约93分钟内处理了96,945个文档中的44,000个文档后获得一个MongoCursorNotFoundException。

MongoIterable<MasterDocument> query = masterCollection.find().noCursorTimeout(true);
    for (MasterDocument masterDocument : query) { ... do some stuff ... }

“做一些事情”部分需要一段时间,这就是为什么整个循环需要这么长时间的原因。

我的问题是,在处理集合中可能一半的文档后,我会得到这个异常。

我正在Windows10笔记本电脑上本地运行客户端应用程序和mongod服务器,通过localhost访问服务器。

服务器日志显示了大量类似于以下内容的消息:

{"t":{"$date":"2021-01-04T20:21:35.510-08:00"},"s":"I",  "c":"COMMAND",  "id":51803,   "ctx":"conn27","msg":"Slow query","attr":{"type":"command","ns":"master_database.MasterCollection","command":{"find":"MasterCollection","filter":{"hashCode":1753339282},"$db":"master_database","lsid":{"id":{"$uuid":"6a252f51-2c6e-4c01-ae03-1a80aab109e0"}}},"planSummary":"COLLSCAN","keysExamined":0,"docsExamined":96944,"cursorExhausted":true,"numYields":96,"nreturned":0,"queryHash":"DBC59907","planCacheKey":"DBC59907","reslen":121,"locks":{"ReplicationStateTransition":{"acquireCount":{"w":97}},"Global":{"acquireCount":{"r":97}},"Database":{"acquireCount":{"r":97}},"Collection":{"acquireCount":{"r":97}},"Mutex":{"acquireCount":{"r":1}}},"storage":{},"protocol":"op_msg","durationMillis":147}}

这些消息的最后一条后面是:

{"t":{"$date":"2021-01-04T20:21:35.521-08:00"},"s":"I",  "c":"NETWORK",  "id":22944,   "ctx":"conn27","msg":"Connection ended","attr":{"remote":"127.0.0.1:58990","connectionId":27,"connectionCount":14}}

{“T”:{“$Date”:“2021-01-04T20:21:35.522-08:00”},“S”:“i”,“C”:“Network”,“ID”:22944,“CTX”:“Conn26”,“Msg”:“Connection Ended”,“ATTR”:{“Remote”:“127.0.0.1:58989”,“ConnectionID”:26,“ConnectionCount”:13}}{“T”:{“$Date”:“2021-01-04T20:21:35.922-08:00”},“S”:“i”,“C”:“-”,“ID”:20883,“CTX”

我试过:

  • 在查询游标上使用“nocursortimeout(true)”(如上图所示)
  • 使用“Mongod--SetParameter LocalLogicalSessionTimeoutMinutes=240”启动服务器。最后一个结果似乎导致了其他日志消息显示“错误”:“Location13111:field(expireAfterSeconds)long!=int”

我正在使用mongod 4.4和最新的mongo Java API。


共1个答案

匿名用户

您可能需要在所有碎片和Mongo中将默认光标空闲超时增加到更大的值:

检查参数(默认值为10 min=600000 ms):

use admin
db.runCommand({getParameter:1, cursorTimeoutMillis: 1})

并更新到更大的值:

use admin
db.runCommand({setParameter:1, cursorTimeoutMillis: 600000000 })

日志中的COLSCAN也表明您在查询中不使用索引,也许您需要在“hashcode”上创建一个...