Nodejs - node-mysql 循环事务

Nodejs - node-mysql transaction with a loop

我的nodejs项目目前使用node-mysql

我有一个多级数据数组,我想将其插入到多个表中。交易是我为了完成我的目标而想到的。以下是我的代码大纲:

const mysql = require("mysql")
const pool = mysql.createPool({ // connectionLimit=10 by default
    connectionLimit: 5, // 10 by default
    host: 'somehost', 
    user: 'userblah',
    password: 'passworblah', 
    database: 'dbblah'
})

pool.getConnection(function(err, dbConnection) {

dbConnection.beginTransaction(function(err1) {
        if (err1) {
            console.log(“Unable to begin the transaction”)
            return
        }

        arrayElements.forEach(function(element) {
            var insert1 = mysql.format(“INSERT INTO table1(…) VALUES (…)”, […])
            dbConnection.query(insert1, function(error1, result1) {
                if (error1) {
                    return dbConnection.rollback(function() {
                        console.log(“Insert failed”)
                    })
                }

                const lastID = result1.insertId

                // A: more loops coming here to insert sub-data to more tables with lastID

                // B: SHOULD I dbConnection.commit here???
            })
        })
    }
}

我认为 dbConnection.commitB 还为时过早(forEach 正在进行中)?我应该怎么做才能确保一切都完成,然后 commit?

您忽略了数据库调用基本上是 IO 调用。他们需要时间来处理。因此,当您在 forEach 中调用插入语句时,所有调用都会被命中,它们不会等待您的查询回答。

var async = require('async')
const mysql = require("mysql")
const pool = mysql.createPool({ // connectionLimit=10 by default
    connectionLimit: 5, // 10 by default
    host: 'somehost', 
    user: 'userblah',
    password: 'passworblah', 
    database: 'dbblah'
})

pool.getConnection(function(err, dbConnection) {

dbConnection.beginTransaction(function(err1) {
        if (err1) {
            console.log(“Unable to begin the transaction”)
            return
        }

        Async.eachSeries(arrayElements,function iteratorOverElems(element,callback) {
            var insert1 = mysql.format(“INSERT INTO table1(…) VALUES (…)”, […])
            dbConnection.query(insert1, function(error1, result1) {
                if (error1) {
                    return callback(err)
                    })
                }

                const lastID = result1.insertId
            moreInsertion(arguments,
                   function (err,result){
                    if(err){
                        return callback(err)
                    }
                   // A: more loops coming here to insert sub-data to more tables with lastID       
                   //now return the iterator
                   return callback();
                   })

            })
        },function finalCb(err){
                    if(err){
                       //rollback
                    }else{
                    // commmit here when all the insertions have been successful            
                     }
    });
    }
}

这不是最终代码。你需要努力。使用异步库管理 forEach 循环函数中每个元素的异步函数处理。

我认为你应该在所有查询都成功时提交,否则回滚。

async.eachSeries 的工作方式类似于为每个 Element 调用迭代器。如果使用 err 参数调用回调,则忽略其余元素并调用最终回调。有关更多详细信息,请参阅异步文档 https://github.com/caolan/async#each