Mongoose模型无法访问进行中事务连接的问题排查
MongoDB多文档事务报错解决方案:Given transaction number 1 does not match any in-progress transactions
首先先明确你的第一个假设:后续路由中引入的模型都指向同一已连接的连接,这个假设是正确的。因为Mongoose是单例模式,所有通过mongoose.model()创建的模型都会默认绑定到Mongoose的当前连接上,只要你只建立了一个数据库连接,所有路由里的模型都会共享这个连接。
接下来我们分析报错原因并给出具体解决方案:
核心问题分析
你遇到的事务编号不匹配错误,主要是因为手动管理事务生命周期(启动、提交、回滚)时容易出现上下文不一致,再加上代码里存在一个容易被忽略的语法错误,共同导致了事务异常。
具体解决方案
1. 修正数据库连接文件(./db/index.ts)
首先修正state对象的语法错误,同时简化连接逻辑,确保存储的是实际的MongoDB连接对象:
const fs = require('fs'); const path = require('path'); const mongoose = require('mongoose'); // 修正对象属性赋值语法(将=改为:) const state = { connection: null }; // 加载所有模型(模型会自动注册到Mongoose的默认连接) const modelFiles = fs.readdirSync(path.join(__dirname, 'models')); modelFiles .filter(fn => fn.endsWith('.js') && fn !== 'index.js') .forEach(fn => require(path.join(__dirname, 'models', fn))); const connect = async () => { // 连接数据库,成功后直接存储实际的连接对象 await mongoose.connect('你的数据库连接字符串'); state.connection = mongoose.connection; return; } const get = () => state.connection; module.exports = { connect, get };
2. 修正路由事务逻辑
使用Mongoose推荐的session.withTransaction()方法自动管理事务生命周期,同时修正更新操作符的错误:
const ExampleModel = require('../db/models/example.model'); const db = require('../db/index'); router.post('/changeQty', async (req,res,next) => { const connection = db.get(); const session = await connection.startSession(); const { someData } = req.body.data; try { // 使用withTransaction自动处理事务的启动、提交、回滚 await session.withTransaction(async () => { const promiseArr = someData.map(data => ExampleModel.findOneAndUpdate( { _id: data.id }, { $inc: { qty: data.qty } }, // 修正错误操作符:$incr → $inc { new: true, runValidators: true } ).session(session) // 绑定当前事务会话 ); await Promise.all(promiseArr); }); return res.status(200).json({ message: '库存更新成功' }); } catch(err) { console.error('事务执行失败:', err); return res.status(500).json({ err: err.message }); } finally { session.endSession(); } })
关键说明
withTransaction()方法会自动处理事务的全生命周期,避免手动调用startTransaction、commitTransaction、abortTransaction时可能出现的上下文不一致问题。- 你代码里的
$incr是错误的MongoDB操作符,正确的自增操作符是$inc,这个错误会导致更新操作失败,间接触发事务异常。 - 所有模型操作必须通过
.session(session)绑定到当前事务会话,确保操作在事务上下文内执行。
内容的提问来源于stack exchange,提问作者sami_analyst
相关产品推荐
相关产品推荐

