【问题标题】:Nodejs - node-mysql transaction with a loopNodejs - 带有循环的 node-mysql 事务
【发布时间】:2016-05-16 05:03:00
【问题描述】:

我的 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???
            })
        })
    }
}

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

【问题讨论】:

    标签: node.js transactions commit node-mysql


    【解决方案1】:

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

    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            
                         }
        });
        }
    }
    

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

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

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

    【讨论】:

    • 谢谢,async 提示!
    猜你喜欢
    • 1970-01-01
    • 2012-05-27
    • 2011-03-20
    • 1970-01-01
    • 2019-08-17
    • 2021-12-28
    • 1970-01-01
    • 2012-05-09
    相关资源
    最近更新 更多