如何防止MySQL交易在Node.js Express中同时执行?
我真的很努力地实现我认为非常琐碎的东西,这使我发疯。
我只希望以下MySQL数据库交易是相互排斥的。因此,第二个电话必须等到第一个电话完成。
我已经尝试了NPM的Async-Mutex框架,将所有内容包裹在MySQL中的“ select ... for select ...”中,但这些都没有导致预期的结果。
当前的行为如下:当2个HTTP请求同时加入并调用以下模型函数时,它们都会输入canentrybeinsert的功能,显然会导致错误的结果。我想拥有
1 2 1 2
,
但我得到
1 1 2 2
。
exports.addEntry = function (entry_id, type) {
return new Promise(function (resolve, reject) {
console.log("1")
beginTransactionP().then(function () {
canEntryBeInserted(entry_id, type).then(function (canBeInserted) {
if (canBeInserted) {
addEntrySQL(entry_id, type).then(function(){
finishTransactionP().then(function() {
console.log("2")
resolve();
})
})
} else {
finishTransactionP().then(function() {
console.log("2")
resolve();
})
}
})
})
})
}
addEntrySQL = function(entry_id, type){
return new Promise(function (resolve, reject) {
sql.query("INSERT INTO entry (entry_id, typ, time) VALUES (?, ?, NOW());", [entry_id, type], function (err, rows, fields) {
if (err) {
console.log("error: ", err);
reject(err);
}
else {
console.log("Inserted successfully.")
resolve();
}
});
})
}
canEntryBeInserted = function (entry_id, type) {
return new Promise(function (resolve, reject) {
sql.query("SELECT * FROM entry WHERE entry_id = ? AND typ = 1 UNION SELECT * FROM entry WHERE entry_id = ? ORDER BY entry_id DESC LIMIT 1;", [entry_id, entry_id], function (err0, rows0) {
console.log(JSON.stringify(rows0), type)
if (err0) {
console.log("error: ", err0);
reject(err0)
}
else if ((rows0.length == 1 && (rows0[0].typ == type || rows0[0].typ == 1)) || rows0.length == 2) {
console.log("Error: Not a valid operation.");
resolve(false)
}
else {
resolve(true)
}
})
})
}
I'm really struggling to achieve something I actually consider to be pretty trivial and it is driving me crazy.
I just want the following MySQL database transaction to be mutually exclusive. So a second call would have to wait until the first call is finished.
I already tried async-mutex framework from npm, wrapping all in promises, the SELECT ... FOR UPDATE clause from MySQL but none of these lead to the expected result.
The current behaviour is the following: when 2 HTTP requests come in simultaneously and call the following model function, they both enter the canEntryBeInserted function obviously leading to wrong results. I would like to have
1 2 1 2
but I get
1 1 2 2
.
exports.addEntry = function (entry_id, type) {
return new Promise(function (resolve, reject) {
console.log("1")
beginTransactionP().then(function () {
canEntryBeInserted(entry_id, type).then(function (canBeInserted) {
if (canBeInserted) {
addEntrySQL(entry_id, type).then(function(){
finishTransactionP().then(function() {
console.log("2")
resolve();
})
})
} else {
finishTransactionP().then(function() {
console.log("2")
resolve();
})
}
})
})
})
}
addEntrySQL = function(entry_id, type){
return new Promise(function (resolve, reject) {
sql.query("INSERT INTO entry (entry_id, typ, time) VALUES (?, ?, NOW());", [entry_id, type], function (err, rows, fields) {
if (err) {
console.log("error: ", err);
reject(err);
}
else {
console.log("Inserted successfully.")
resolve();
}
});
})
}
canEntryBeInserted = function (entry_id, type) {
return new Promise(function (resolve, reject) {
sql.query("SELECT * FROM entry WHERE entry_id = ? AND typ = 1 UNION SELECT * FROM entry WHERE entry_id = ? ORDER BY entry_id DESC LIMIT 1;", [entry_id, entry_id], function (err0, rows0) {
console.log(JSON.stringify(rows0), type)
if (err0) {
console.log("error: ", err0);
reject(err0)
}
else if ((rows0.length == 1 && (rows0[0].typ == type || rows0[0].typ == 1)) || rows0.length == 2) {
console.log("Error: Not a valid operation.");
resolve(false)
}
else {
resolve(true)
}
})
})
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
以下代码说明了异步函数如何获得锁定,该函数可以防止并发执行,直到再次释放锁。
这将在全局变量
锁定
中维护JavaScript级别上的锁定。您可能需要一些更细颗粒的东西。与
选择更新
的数据库级别锁定也是可能的,但是如果失败了,请求必须重试直到成功,因为数据库不会发射Release> Release
Event就像上面的代码一样。The following code demonstrates how an asynchronous function can acquire a lock, which prevents concurrent execution until the lock is released again.
This maintains the lock on the Javascript level in the global variable
lock
. You may need something more fine-granular.A database level lock with
select for update
is also possible, but if that fails the request would have to try again until it succeeds, because the database does not emit arelease
event like the code above.