Postgresql 捕获事务错误并回滚

Postgresql Catching Transaction Error and Rollback

我正在使用 pg-promise 来 运行 我的 SQL 查询。查询本身存储在外部 .sql 文件中。

当我执行事务时,如果发生错误(如预期),Postgres 将中止事务。我 运行 遇到的问题是在事务中止后我尝试 运行 的任何单独查询都不是 运行 而是我收到此消息: "current transaction is aborted, commands ignored until end of transaction block"。如果查询在 psql 控制台中被 运行,我可以通过在查询失败后发出 ROLLBACK 来解决这个问题。我不认为这是一个选项,因为我的应用程序使用的 SQL 位于外部文件中。我也不认为 Savepoints 是一个选项,因为如果出现故障,整个事务都应该被丢弃。

如果发生此错误,我如何在 SQL 文件中回滚?

这里是SQL供参考:

BEGIN;

DELETE 
FROM tournament_tossup_values
WHERE tournament_id =  AND
NOT EXISTS
(
    SELECT id
    FROM tournament_match
    WHERE tournament_id = 
);

UPDATE tournament
SET bonus_point_value = , parts_per_bonus = 
WHERE id =  AND NOT EXISTS (
    SELECT id 
    FROM tournament_match
    WHERE tournament_id = 
)
RETURNING bonus_point_value, parts_per_bonus; <-- Any subsequent accesses to the database by the application fail if this transaction fails

COMMIT;  <-- I want to rollback everything if this fails

提前致谢!

在外部 SQL 文件中实现事务时,您需要为 COMMITROLLBACK 提供所有正确的处理。如果您不这样做,事务状态可能会在您的服务器端代码中变得不可预测,并导致您遇到的错误类型。

这可能有点棘手,说起来容易做起来难。这就是为什么最好的解决方案是根本不这样做。

模块 pg-promise that you are already using provides reliable handling for transactions, via method tx,这是您应该使用的。

来自 tx 方法文档:

Executes a callback function as a transaction (...)

A transaction wraps a regular task into additional queries:

it executes BEGIN just before invoking the callback function

it executes COMMIT, if the callback didn't throw any error or return a rejected promise, it executes ROLLBACK, if the callback did throw an error or return a rejected promise

it executes corresponding SAVEPOINT commands when the method is called recursively.

为此,将您的 SQL 文件分成两个文件 - 一个包含您的 DELETE 操作,一个包含您的 UPDATE 操作,然后将它们作为两个查询在一个交易:

await db.tx(async t => {
    await t.none('DELETE...');
    await t.any('UPDATE...');
});