You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB 4.2.6批量插入事务失败求助(ReactiveMongo驱动)

问题分析与解决办法

结合你的环境(MongoDB 4.2.6 + Play 2.7.x + ReactiveMongo 0.18.4-play27)和错误信息(错误码251,NoSuchTransaction),这个问题的核心原因是ReactiveMongo 0.18.x版本在事务中执行批量插入(insertMany)时,默认的多批次(multi-bulk)操作没有正确将事务会话上下文传递到所有批次请求。

当你执行insert(false).many(...)时,ReactiveMongo会根据文档数量自动拆分多个批量请求,而旧版本的驱动没有确保每个批量请求都绑定同一个事务会话,导致后续批次请求找不到已开启的事务,从而抛出"Given transaction number 1 does not match any in-progress transactions"的错误。而单条插入(insertOne)只发送一个请求,事务上下文能正确传递,所以可以正常执行。

另外,你的代码里还有一个小问题:在writeResultFuture.map中调用dbWithTnx.commitTransaction().flatMap{ _ => sessionDb.endSession() }会导致Future嵌套,无法正确等待事务提交和会话关闭完成,这可能会引发其他潜在问题。


解决办法

1. 强制单批次插入(快速修复)

禁用ReactiveMongo的自动多批次拆分,将所有文档放在一个批量请求中发送,确保事务上下文能正确传递。你可以通过设置maxDocsPerBulk为文档总数,确保所有文档在同一批次发送:

修正后的业务代码示例:

reactiveMongoApi.database.flatMap { db: DefaultDB =>
  db.startSession().flatMap {
    case Some(sessionDb) =>
      sessionDb.startTransaction(Option(WriteConcern.Default)) match {
        case None => Future.successful(println("Database replica is not initiated"))
        case Some(dbWithTnx: DefaultDB) =>
          val collFoo = dbWithTnx.collection[BSONCollection]("foo")
          val docs = Seq(BSONDocument("name" -> "Jack"), BSONDocument("name" -> "Ma"))
          // 强制单批次插入,指定批量大小为文档总数
          val writeResultFuture = collFoo.insert(false)
            .many(docs, maxDocsPerBulk = docs.size)
          
          // 用flatMap代替map,确保等待commit和endSession完成
          writeResultFuture.flatMap { wr =>
            println(wr)
            dbWithTnx.commitTransaction().flatMap { _ =>
              sessionDb.endSession()
            }
          }
      }
    case None => Future.successful(println("None"))
  }
}

2. 升级ReactiveMongo版本(彻底解决)

ReactiveMongo在后续版本(比如0.19.x及以上)中修复了事务中批量操作的上下文传递问题。你可以升级build.sbt中的依赖到最新兼容Play 2.7的版本:

libraryDependencies ++= Seq(
  "org.reactivemongo" %% "play2-reactivemongo" % "0.19.7-play27"
)

注意:升级前请确认版本兼容性,避免API变动带来的适配问题。

3. 修正Future处理逻辑

确保所有异步操作(事务提交、会话关闭)都被正确等待,避免Future嵌套。使用flatMap代替map来处理后续的异步操作,保证整个流程的异步连贯性。


额外验证点

  • 确认你的MongoDB集群是副本集(事务仅支持副本集,不支持单节点),从错误信息中的TransientTransactionError来看集群状态正常,但可以再检查副本集运行状态。
  • 事务中建议使用WriteConcern.Majority来确保数据一致性,你可以在启动事务时指定该参数。

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 18:28:02