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.commit
在 B
还为时过早(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
我的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.commit
在 B
还为时过早(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