node.js - 使用 Mongoose 事务的长/大写操作的 TransientTransactionError/NoSuchTransaction 问题

标签 node.js mongodb mongoose transactions

我已经运行了几个月的 NodeJS 代码库,每天一次,它从外部 API 获取相对大量的数据,然后将数据写入托管的 MongoDB Atlas 实例。这个写操作几个月来都没有问题,并且在过去的几天里,我尝试迁移代码以使用 Mongoose 中的 session /事务来执行写操作。 但是,我无法可靠地提交操作,因为它经常因 TransientTransactionError 而失败,原因是 NoSuchTransaction。

它在一个特定部分一直失败,我试图将大约 80mb/36,000 个文档写入数据库。该操作通常需要 3-5 分钟才能完全完成,而且我以前在不使用事务时从未遇到过任何写入问题。我也试过将数组拆分成一个 For 循环,它在其中对其组成部分执行许多小的写操作,但由于同样的原因,这也失败了。是否有我没有看到的超时参数或连接可以打开的最长时间?我觉得我非常密切地关注文档中的代码示例,但无法弄清楚为什么它会遇到问题。我还尝试了 mongo 文档中概述的 session.withTransaction() 模式,但由于同样的原因也失败了。

写入操作在没有事务的情况下工作正常,还有其他写入操作在事务中使用 insertMany() 成功完成,但我将它们从下面的代码片段中删除,因为它们不会导致任何失败,并且只是隔离了抛出异常的部分。

var mongoose = require('mongoose');
var dailyDataCollection = mongoose.model('DailyDataCollection')

( async () => {
    var dbUrl = config.MONGODB_PREFIX+'://'+config.MONGODB_USERNAME + ':' + config.MONGODB_PASSWORD + '@' + config.MONGODB_HOSTNAME+'/'+config.MONGODB_DATABASE + '?retryWrites=true&w=majority';
    var database = await mongoose.connect(dbUrl, { useNewUrlParser: true, user: config.MONGODB_USER, pass: config.MONGODB_PASSWORD, useCreateIndex: true, useUnifiedTopology: true})
    var session = await database.startSession();
    try{
        await performDailyDataPull(session)
    }
    finally{
        await session.endSession();
        await database.disconnect()
    }
} 
)();

const performDailyDataPull = async(session) => {
    var veryLargeArray = await externalAPI.getTodaysData()

    await session.startTransaction()
    
    await writeVeryLargeArrayToDB(veryLargeArray, session)
    
    await session.commitTransaction()
}

const writeVeryLargeArrayToDB = async(veryLargeArray, session) => {
    try
    {
        await dailyDataCollection.insertMany(veryLargeArray, { session: session })
    }
    catch(e)
    {
        console.log(e)
    }   
}

跟踪片段

[Symbol(errorLabels)]: Set { 'TransientTransactionError' } }
codeName: NoSuchTransaction
message:'Transaction 2 has been aborted.'

最佳答案

您可能需要延长交易生命周期:

 db.adminCommand( { setParameter: 1, transactionLifetimeLimitSeconds: 600 } )

关于node.js - 使用 Mongoose 事务的长/大写操作的 TransientTransactionError/NoSuchTransaction 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66051131/

相关文章:

node.js - token 无效或提供的状态 token 无效

javascript - Mongoose 查询返回未定义的字符串

java - 使用 mongofiles 实用程序访问通过 Java GridFS API 插入的数据

mongodb - 在 symfony 2.1 中使用 mongodb 进行用户身份验证

mongodb - 按子文档大小查找 MongoDB 文档

json - mongoose find() 输出隔离

javascript - Mongoose 无法更新数组 : undefined error

javascript - Cypress - 如何使用 RegEx 进行负向预测?

javascript - 需要 highcharts-browserify 才能使用特定版本的 highcharts?

javascript - Node.js 中的全局包导入