如何使用node-postgres进行事务处理?

4
我正在使用node-postgres以回调的方式进行SQL查询。我有一个函数,它接收一个查询列表并在事务块内执行它们。我的理解是使用node-postgres提交查询“BEGIN”,在我的事务块中提交所有需要的查询,然后提交查询“COMMIT”。
然而,尽管我的查询有效(简单插入,作为独立查询经过了充分测试),而且一切都按正确顺序执行,但在事务块之后测试数据库状态时,我得到了不一致的状态。有时候我所有的插入都发生了,有时只有其中一部分。我的理解是事务块是原子性的,所以在提交之后立即使用SELECT查找它们时,块内的插入应该全部成功或全部失败。
下面是我的函数:
Db.prototype.makeTransaction = function (queries, callback) {
    var thisDb = this;
    thisDb.tryQuery("BEGIN", [], function () {
        async.forEach(queries, function (query, arrayCallback) {
            thisDb.tryQuery(query.sql, query.values, arrayCallback);
        }, function (err) {
            if (err) {
                thisDb.tryQuery("ROLLBACK", [], function () {
                    callback(err);
                });
            } else {
                thisDb.tryQuery("COMMIT", [], callback);
            }
        });
    });
};

使用辅助函数tryQuery:

Db.prototype.tryQuery = function (query, values, callback) {
    pg.connect(this.conn, function (err, client) {
        if (!err) {
            client.query(query, values, callback);
        } else {
            // Failed to connect to the database
            callback(err);
        }
    });
};

有没有想法是哪里出了问题?

1
pg.connect 每次调用是否保证返回相同的连接?考虑在服务器上启用语句日志记录以查看发生了什么(并在服务器 log_line_prefix 中包括连接和会话 ID)。 - araqnid
我不能保证返回相同的连接;实际上,我几乎肯定会得到不同的连接。但是,由于我的回调结构,这不应该成为问题。我在“BEGIN”之后回调,然后在事务中的(异步)查询之后回调,最后在“COMMIT”之后回调。 无论是否为不同的查询使用不同的连接,它都应该按正确顺序执行,这才是最重要的,对吧? - ferson2020
或者说组成事务块的查询必须在同一个连接上执行吗?您能否解释一下不同连接的含义,或者提供一个链接给我? - ferson2020
但是你正在重复调用tryQuery函数,每次它都会调用pg.connect来执行查询,不是吗?或者如果this.conn已经连接,它会跳过连接吗? - araqnid
3
在事务块中,命令必须在同一连接上执行。 - araqnid
那么就这样解释了,非常感谢! - ferson2020
1个回答

3
感谢araqnid回答我的问题:事务必须在同一连接上完成。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接