AWS运行程序读取MongoDB出现pymongo.errors.CursorNotFound错误求助
问题根因
pymongo.errors.CursorNotFound本质是MongoDB服务端的游标已经被销毁,客户端再尝试通过该游标拉取数据时触发的报错,对应你的场景常见触发原因如下:
- MongoDB默认游标闲置超时时间为10分钟,40万文档遍历过程中,如果单批次拉取的文档处理耗时超过10分钟,服务端会自动销毁无活动的游标,你第二次拉取数据时就会触发报错
- 你运行在AWS环境,近期可能出现MongoDB实例(自建或托管DocumentDB)负载升高、网络波动,导致文档拉取速度变慢、单批处理耗时刚好超过阈值,这也是无配置变更突然报错的常见原因
- 游标遍历过程中连接意外中断,或程序隐性触发了连接重置,也会导致原有游标失效
可行解决方案
方案1:关闭单次查询的游标超时
适合数据处理总耗时不超过几小时的场景,查询时增加no_cursor_timeout=True参数禁用游标自动超时:
# 修改前 table_data = db.your_collection.find(your_query) # 修改后 table_data = db.your_collection.find(your_query, no_cursor_timeout=True)
注意:游标使用完成后必须手动调用table_data.close()释放资源,避免服务端出现游标泄漏占用内存
方案2:配合调整批量拉取大小
和方案1搭配使用,调整batch_size参数控制单次拉取的文档数量,减少服务端交互次数的同时避免单批数据处理耗时过长:
# 可根据单文档大小、机器内存调整单批拉取数量,一般设置为500-2000即可 table_data = db.your_collection.find(your_query, no_cursor_timeout=True, batch_size=1000)
方案3:分页查询完全规避游标问题
适合数据量极大、处理总耗时很长的场景,用_id作为分页标记替代全局游标,完全不会出现游标超时问题,还支持断点续跑:
last_id = None batch_size = 1000 while True: query = your_query.copy() if last_id: query["_id"] = {"$gt": last_id} current_batch = list(db.your_collection.find(query).limit(batch_size)) if not current_batch: break # 处理当前批次的文档 for row in current_batch: process_your_row(row) # 更新分页标记 last_id = current_batch[-1]["_id"]
方案4:调整服务端超时配置
如果你使用的是AWS托管的DocumentDB实例,可以到控制台修改对应参数组的cursorTimeoutMillis参数,将默认的600000(10分钟)调整为更大的数值,该配置为实例全局配置,会影响所有连接的游标超时逻辑。
内容的提问来源于stack exchange,提问作者MaxxABillion
相关产品推荐
相关产品推荐

