我正在使用node-sqlite3,但我确信这个问题也出现在另一个数据库中。我在我的代码中发现了一个混合事务和异步代码的错误。
function insertData(arrayWithData, callback) {
// start a transaction
db.run("BEGIN", function() {
// do multiple inserts
slide.asyncMap(
arrayWithData,
function(cb) {
db.run("INSERT ...", cb);
},
function() {
// all done
db.run("COMMIT");
}
);
});
}
// some other insert
setInterval(
function() { db.run("INSERT ...", cb); },
100
);
您还可以运行完整的示例。
问题是在 or 之后的异步暂停期间可以启动其他一些带有or查询的insert
代码。然后这个额外的查询在事务中运行。提交事务时,这不是问题。但是,如果事务被回滚,那么这个额外查询所做的更改也会被回滚。哎呀,我们只是意外地丢失了数据而没有任何错误消息。update
begin
insert
我考虑过这个问题,我认为一种解决方案是创建一个包装类,以确保:
- 只有一个事务在同时运行。
- 当事务正在运行时,仅执行属于该事务的查询。
- 在当前事务完成后,所有额外的查询都会排队并执行。
- 当一个事务已经运行时,所有启动事务的尝试也将排队。
但这听起来像太复杂的解决方案。有更好的方法吗?你如何处理这个问题?