当前位置: 首页
数据库
如何优雅捕获Node.js项目中的MongoDB写入异常

如何优雅捕获Node.js项目中的MongoDB写入异常

热心网友 时间:2026-07-08
转载

先说一个核心判断:insertMany 写入失败时,并不会抛出一个统一的错误类型。你可能会遇到 MongoWriteConcernErrorMongoBulkWriteErrorMongoServerError(比如 code 11000 代表重复键),甚至原生 Error(网络中断)。关键不在于看 error.name,而是要盯住 error.codeerror.writeErrors——对于批量写入来说,后者尤其重要。

Node.js项目中如何优雅地捕获MongoDB写入异常?

写入失败时 insertMany 抛什么错误?

实际上,MongoDB 驱动会根据具体失败原因返回不同错误对象:写关注没满足,给你 MongoWriteConcernError;批量写入中部分失败,给你 MongoBulkWriteError;常规服务端错误如重复键,则是带 code: 11000MongoServerError;当然还有网络中断这种原生 Error。所以判断逻辑要围绕 error.codeerror.writeErrors 展开,别只盯着 error.name——它往往不靠谱。

为什么 try/catch 捕不到“控制台没输出”?

这种情况十有八九是变量名引用问题。举个例子:你明明用 const Model = require("./models/match") 导入,结果在路由里写了 await Match.insertMany(...)。那好,Match is not defined 这个 ReferenceError 在函数刚开始执行时就被抛出了——同步语法错误,try/catch 根本抓不住,因为整个 async 函数体还没走到 await 那一行,当然不会有任何输出。

所以检查顺序很简单:

  • 核对模型中使用的变量名和 require 时定义的名字是否完全一致,大小写、拼写都不能马虎。
  • 确认模型已正确导出,没有丢三落四。
  • catch 块里加上 console.error(error.stack) 而不是只打印 error.message——堆栈信息能告诉你错在哪一行。

insertMany 部分失败时怎么拿到具体哪几条错了?

insertMany 默认走 ordered: true,即遇到第一条错误就立刻刹车。但只要改成 ordered: false,它就会继续处理剩余数据,最后通过 error.writeErrors 数组把每条失败项的索引、错误码和详情全抛给你:

try {  const result = await Model.insertMany(data, { ordered: false });} catch (error) {  if (error.writeErrors) {    error.writeErrors.forEach(({ index, code, errmsg }) => {      console.warn(`第 ${index} 条数据写入失败(code ${code}):`, errmsg);    });  }}

这里有几个常见错误码值得记住:

  • code: 11000 —— 唯一键冲突,解决方法通常是去重,或者改用 updateOne 配合 upsert
  • code: 121 —— 文档验证失败,回头看看 schema 里的 requiredvalidate 规则是不是太严了。
  • 另外,ordered: false 虽然不影响成功写入的数据,但错误堆栈会明显变长,生产环境最好加上日志采样,免得被海量错误信息刷屏。

事务中写入失败,commitTransaction 还会执行吗?

答案是否定的。commitTransaction 只有在显式调用时才会触发,而一旦某次 collection.insertOne 失败并抛出异常,驱动会自动 abort 当前事务,commitTransaction 那行代码根本执行不到。所以你能拿到错误码的地方只有两个:要么是 CRUD 操作本身(比如 insertOnecode: 133 写冲突),要么是显式调用 commitTransaction 时(可能报 code: 112251)。

  • 千万不要在 catch 里默认事务已经提交——老老实实检查 session.inTransaction() 的状态。
  • 注意 code: 112 并不代表写冲突(写冲突是 133),它更可能意味着会话过期或事务超时。这时候要结合 error.errorLabels?.includes('TransientTransactionError') 来判断能否重试。
  • 如果事务内某个操作因为 maxTimeMS 设置太短而超时,错误码是 code: 50MaxTimeMSExpired),这发生在具体命令层,可不是 commit 阶段的问题。

说到这里,核心结论就很清晰了:事务写入异常的根因往往不在 commit 那一刻,而在你第一次调用 insertOneupdateMany 的瞬间。错误码早就藏在那里了,别等到 commitTransaction 才去找原因。

来源:https://www.php.cn/faq/2784736.html

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
配置Java应用支持Oracle数据库AD/Kerberos身份验证

配置Java应用支持Oracle数据库AD/Kerberos身份验证

配置Java应用支持OracleAD Kerberos需正确设置JVM的krb5 conf与jaas conf,JDBCURL添加oracle net authentication_services=(KERBEROS5)并与SPN严格匹配。AD用户需映射为Oracle企业用户并授予CREATESESSION权限。SPN注册和EUS映射是常见故障点。

时间:2026-07-08 07:04
Redis订阅者BGSAVE期间响应变慢:RDB持久化IO影响分析

Redis订阅者BGSAVE期间响应变慢:RDB持久化IO影响分析

Redis订阅者在BGSAVE期间响应变慢,源于fork阻塞、COW内存争抢及磁盘I O高负载三重叠加。通过将RDB迁移至从节点、禁用THP、调整swappiness并手动触发避开高峰,可有效降低对主服务的影响。

时间:2026-07-08 07:03
如何优雅捕获Node.js项目中的MongoDB写入异常

如何优雅捕获Node.js项目中的MongoDB写入异常

批量插入失败时不会抛出统一错误类型,需关注错误代码和写入错误数组。部分失败时可设置有序参数为假以获取写入错误数组。事务中写入失败会自动中止事务,提交事务不会执行。常见错误码11000为唯一键冲突,121为文档验证失败。

时间:2026-07-08 07:03
如何用SQL窗口函数ROW_NUMBER实现分组内去重

如何用SQL窗口函数ROW_NUMBER实现分组内去重

行号函数仅分配行序号,不能直接去重。需通过子查询或公用表表达式过滤行号为1的行,实现分组内去重。若排序字段有重复,应加入唯一键以保证排序稳定性。还需注意不同数据库对空值排序的差异及版本兼容性。

时间:2026-07-08 07:03
Spring Boot RedisTemplate无法直接注入?检查泛型声明是否正确

Spring Boot RedisTemplate无法直接注入?检查泛型声明是否正确

RedisTemplate注入失败多因泛型擦除导致类型不匹配,需保证配置类返回类型、注入字段类型及内部key value类型三者一致。避免使用无泛型或通配符形式,不同序列化策略应定义独立Bean并用@Qualifier区分。StringRedisTemplate为独立Bean,不可混用。

时间:2026-07-08 07:03
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 日榜
  • 周榜
  • 月榜