node.js sqlite 事务隔离

node.js sqlite transaction isolation

如何确保 SQLite 不会交错来自多个并发节点的查询。js/Express HTTP 请求到单个事务中?

我希望来自不同请求的数据库查询在单独的事务中执行,彼此隔离,允许每个事务彼此独立地提交或回滚。考虑到 node.js 的单线程(和单数据库连接?)特征,这似乎特别有问题。

我一直在浏览数十个网页和文档,但没有找到任何(对我而言)关于如何(或是否)处理这种情况的明确解释。例如 db.serialize() 的描述只说明一次将执行一个查询 - 它没有说明属于不同事务的查询的分离。

感谢任何指点!

我遇到了完全相同的问题。这是我解决它的方法:

第 1 步:确保所有数据库访问都是通过一组库函数完成的,其中数据库作为第一个输入参数传入。

步骤 2:创建数据库对象时(使用 new sqlite3.Database('path')),用一些额外的元信息包装对象:

这是我的包裹方式:

var wrap = { db_obj : new sqlite3.Database('path'), locked : "UNLOCKED", work_queue : [] }

步骤 3:创建将用于 运行 数据库函数的函数。如果数据库被锁定,这个函数将推迟它们的执行。我打电话给我 "runAsync":

function runAsync( db, fn, callBack) {
    if (db.locked === "LOCKED" ) {
        db.work_queue.push( function() { runAsync( db, fn, callBack ); });
        return;
    }
    fn(db,callBack);
}

我们可以看到这个函数检查了包装的db对象的状态。如果它被锁定,我们通过将函数存储在稍后执行的 "work queue" 中来延迟执行(通过执行 fn())。

第 4 步:创建将用于 运行 数据库函数 独占 的函数。如果数据库被锁定,这个函数将延迟执行,否则它会锁定数据库,运行它的函数然后解锁数据库。我打电话给我:runAsyncExclusive():

function runAsyncExclusive( db, fn, callBack ) {
    if(db.locked === "LOCKED") {
        db.work_queue.push( function() { runAsyncExclusive( db, fn, callBack) });
        return;
    }
    var exclusiveDb = {
        db_obj : db.db_obj,
        locked : "UNLOCKED",
        work_queue : []
    };
    db.locked = "LOCKED";
    fn(exclusiveDb, function(err,res) {
        db.locked = "UNLOCKED";
        var workItems = db.work_queue;
        _.each(workItems, function(fn) { fn(); });
        db.work_queue = [];
        callBack(err,res);
    })
}

传递给函数的 exclusiveDb 对象将允许对数据库进行独占访问。该对象本身可以被锁定,允许任意深度嵌套锁定。

第 5 步:调整您的库函数,使其在适当的地方调用 asyncRun()asyncRunExclusive()

function get(db,sql,params,callBack) {
    db.get(sql,params,callBack);
}

变成...

function get(db,sql,params,callBack) {
    runAsync( db, function(db,cb) { db.get(sql,params,cb); }, callBack );
}

瞧!

(如果不够清楚,请见谅)