首页 > 数据库 >mongodb常见报错

mongodb常见报错

时间:2024-12-26 16:20:45浏览次数:3  
标签:mongodb 常见 游标 cursor 报错 MongoDB com row

mongodb常见报错

目录

MongoDB异常MongoCursorNotFoundException

报错内容:

om.mongodb.MongoCursorNotFoundException: Query failed with error code -5


 Caused by: com.mongodb.MongoCursorNotFoundException: Query failed with error code -5 and error message 'Cursor 400554224227 not found on server 11.11.16.123:17000' on server 11.11.17.251:9000
	 at com.mongodb.operation.QueryHelper.translateCommandException(QueryHelper.java:27)
	 at com.mongodb.operation.QueryBatchCursor.getMore(QueryBatchCursor.java:229)
	 at com.mongodb.operation.QueryBatchCursor.hasNext(QueryBatchCursor.java:115)
	 at com.mongodb.MongoBatchCursorAdapter.hasNext(MongoBatchCursorAdapter.java:46)
	 at com.alibaba.datax.plugin.reader.mongodbreader.MongoDBReader$Task.startRead(MongoDBReader.java:301)
	 at com.alibaba.datax.core.taskgroup.runner.ReaderRunner.run(ReaderRunner.java:57)

cosur

背景:

我遇到这个问题是用datax导数据时我们自定义了mongoreader组件在读取亿级数据量表时报错,数据量大,数据结构复杂,其中所读取的数据库数据较多,因为是线上业务库读取数据的速度被限制,加之当时网络波动,之前运行正常的任务报了游标超时的错误。

问题分析:

你在用 db.collection.find()的时候,它返回的不是所有的数据,而实际上是一个cursor。它的默认行为是:第一次向数据库查询 101 个文档,或 1 MB 的文档,取决于哪个条件先满足;之后每次cursor 中的文档用尽后,查询 4 MB 的文档。另外,find() 的默认行为是返回一个 10 分钟无操作后超时的 cursor。如果一个 batch 的文档十分钟内没处理完,过后再处理完了,再用同一个 cursor id 向服务器取下一个 batch,这时候cursor id 已经过期了,这也就能解释为啥得到 cursor id 无效的错误了。

解决方案

方案一:

修改MongoDB的配置,延长游标超时时间,并重启MongoDB。但是由于生产环境的MongoDB不能随便重启,联系运维可能会拒绝你,所以这个方案有用,但是你也被运维拒绝后可以考虑以下方案。

方案二:

一次性把数据全部读取下来,再做处理,以下是解释实例:

all_data = [row for row in handler.find()]

for row in all_data:
    parse(row)

这种方案的弊端很明显,如果数据量非常大,你不一定能全部放到内存里面,在我们亿级数据量的背景下几乎不可能。即使能够全部放到内存中,但是列表推导式遍历了所有数据,紧接着for循环又遍历一次,浪费时间,所以不推荐,如果在数据量级小完全可以放到内存中可以做类似的尝试。

方案三:

让游标每次返回的数据小于100条,这样消费完这一批数据的时间就会小于10分钟:

#每次连接数据库,只返回50行数据
for row in handler.find().batch_size(100): 
    parse_data(row)

这种方案虽然比较稳妥但是会增加数据库的连接次数,从而增加I/O耗时。试想我们有1亿数据,你把每次连接查询的数据量限制在100或者说是1000次读取这份数据应该要创建最少10万次连接,这种代码被发现后自己想后果。但是如果你的连接创建次数在接受范围内,完全是可以的。

方案四:

让游标永不超时。通过设定参数no_cursor_timeout=True,让游标永不超时:

cursor = handler.find(no_cursor_timeout=True)
for row in cursor:
    parse_data(row)
cursor.close()  # 一定要手动关闭游标

然而这个操作非常危险,因为如果你循环时产生异常,甚至断电或断网,都会导致 MongoDB 服务器资源永远无法被释放。这个游标就再也无法关闭了!除非重启MongoDB,否则这些游标会一直留在MongoDB上,占用资源。
那么有没有什么方法可以规避这个风险,在创建线程或者使用spark时常常会有close()又或者时stop()的方法,我们经常将他们放在必须执行的结构中。所以我们想到了用try catch finally去做。

/ * try catch:自己处理异常
  * try {
  *可能出现异常的代码
  *} catch(异常类名A e){
  *如果出现了异常类A类型的异常,那么执行该代码
  *} ...(catch可以有多个)
  * finally {
  *最终肯定必须要执行的代码(例如释放资源的代码)
  *}

虽然这种方法会对代码美观性造成一定的破坏但是无疑完美的解决了我们的问题。

标签:mongodb,常见,游标,cursor,报错,MongoDB,com,row
From: https://www.cnblogs.com/xulinforDB/p/18633327

相关文章

  • IntelliJ IDEA 2024.3 安装教程与激活方法(附常见问题解决)
    IntelliJIDEA概述IntelliJIDEA是JetBrains公司推出的一款功能强大的Java集成开发环境(IDE),凭借其丰富的功能和工具集,极大地提升了开发者的编程效率和工作体验。温馨提示:本文中的方法仅供学习交流使用,如果条件允许,请支持正版软件。删除旧版本IntelliJIDEA如果您的电脑中已......
  • DataGrip2024.3完整版的安装教程(附激活,常见问题处理)
    卸载老版本DataGrip首先,如果小伙伴的电脑上有安装老版本的DataGrip,需要将其彻底卸载掉,如下所示(没有安装则不用管,直接安装即可):TIP:如果你之前使用过本站提供的 激活到2025年版本脚本,需要执行对应卸载脚本/适用2024版本/JetBrains2023最新全家桶/jetbra/scripts/unin......
  • Eclipse Jgit 不支持高版本 openssh 私钥的结局方法 (jsch 报错 invalid privatekey
    替换jsch依赖<dependency><groupId>org.eclipse.jgit</groupId><artifactId>org.eclipse.jgit.ssh.jsch</artifactId><version>7.1.0.202411261347-r</version><ex......
  • 常见的一些基本运算电路分析
    1.运算放大器    基本运算电路依靠集成运算放大器组成,其电子符号如下:    其由多级放大电路集成,具备两个显著特点:        (1)虚短:两个输入极之间的等效电阻约等于0,使得输入极两极电压始终保持相等,可以认为两个输入极之间处于短路状态。    (2......
  • centos7.9 安装mongodb4.4.8
    安装依赖,命令如下sudoyuminstalllibcurlopensslxz-libs下载压缩包,地址如下https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.4.8.tgz解压压缩包,解压存放路径,根据自己定义来,我这里放到/home目录下tar-zxvfmongodb-linux-x86_64-rhel70-4.4.8.tgz复制......
  • 如何使用 Konga 可视化管理 Kong API 网关:完整指南与常见场景实例
    言简意赅的讲解Konga解决的痛点Kong是一个流行的API网关,广泛应用于微服务架构中,为应用提供负载均衡、API管理、身份验证、流量控制等功能。虽然Kong强大且功能丰富,但其管理界面原本基于命令行和配置文件,可能让部分开发者或运维人员感到不便。为了简化管理操作,Konga......
  • 【Java】Java中的常见日期对象
    类名说明java.util.Date这是Java早期版本中的主要日期类,尽管现在已经被java.time包中的类所取代,但在一些旧代码库中仍然可以看到它的身影java.util.Calendar这是一个抽象类,提供了操作日历字段如年、月、日、时、分、秒的方法。Calendar类本身不能直接实例化,而是通过调......
  • 3种常见的数据库迁移工具对比
    3种常见的数据库迁移工具对比神州数码云基地​已认证账号​关注2人赞同了该文章之前在项目中,收到一个紧急需求,要把数据从 PostgreSQL 迁移到 TiDB 中。由于时间紧任务重,来不及调研高效的方式,直接使用了Navicat内置的功能,把数据从PostgreSQL迁移到......
  • 常见设计原则
    常用设计原则目录单一职责原则开闭原则里氏替换原则接口隔离原则依赖倒置原则迪米特法则单一职责原则单一职责原则(SingleResponsibilityPrinciple,SRP)定义:一个类应该只有一个引起它变化的原因。即一个类应该只负责一项职责。解释:这意味着一个类应该专注于一个......
  • 在域控(Domain Controller,DC)上做快照是一种用于备份和恢复的常见操作,尤其是在 Active D
    在域控(DomainController,DC)上做快照是一种用于备份和恢复的常见操作,尤其是在ActiveDirectory环境中。通过创建域控的快照,可以在发生故障时快速恢复到快照时的状态。下面是如何在WindowsServer上创建域控的快照的步骤:1.使用 WindowsServer快照功能在WindowsServer上......