交易中的交易

Ale*_*lex 21 postgresql transaction postgresql-9.3

例如,如果调用下面的脚本,PostgreSQL 会显示什么行为

BEGIN;
SELECT * FROM foo;
INSERT INTO foo(name) VALUES ('bar');
BEGIN; <- The point of interest
END;
Run Code Online (Sandbox Code Playgroud)

PostgreSQL 会丢弃第二个BEGIN还是隐式决定提交,然后BEGIN END在最后将块作为单独的事务运行?

小智 16

您需要的是所谓的“自治事务”(oracle 提供的功能)。在这一点上,这在 PostgreSQL 中是不可能的。但是,您可以使用SAVEPOINT

BEGIN;
INSERT ...
SAVEPOINT a;
some error;
ROLLBACK TO SAVEPOINT a;
COMMIT;
Run Code Online (Sandbox Code Playgroud)

它不完全是一个自主的交易——但是,它可以让你正确地完成“每一笔交易”。您可以使用它来实现您对自主交易的期望。

否则此时没有其他合理的解决方案。


dez*_*zso 14

你可以自己试试:

警告:已经有一个交易正在进行中

它不会启动新的(子)事务,因为 PostgreSQL 中没有实现嵌套事务。(你可以在一个pl/pgsql例如,模仿该行为函数。)

使用 PostgreSQL 11,人们可以认为新的真实存储过程及其处理事务的能力将使嵌套事务成为可能。但是,根据文档,情况并非如此:

CALL命令调用的过程以及匿名代码块 ( DOcommand) 中,可以使用命令COMMIT和结束事务ROLLBACK。使用这些命令结束事务后会自动启动新事务,因此没有单独的 START TRANSACTION 命令。


Ami*_*ari 11

PostgreSQL 不支持子事务,但该SAVEPOINT功能可以有效地满足您的需求。通过Vitaly Tomilov在 GitHub 上的承诺,从高级访问层到 PG的文档中引用:

PostgreSQL 对嵌套事务没有适当的支持,它只支持通过事务内的保存点进行部分回滚。正如进一步解释的那样,这两种技术之间的差异是巨大的。

对嵌套事务的适当支持意味着当其父事务回滚时,成功的子事务的结果不会回滚。但是对于 PostgreSQL 保存点,如果回滚顶级事务,所有内部保存点的结果也会回滚。

保存点可用于部分回滚到活动事务中较早的点。例如,要建立一个保存点,然后撤消它建立后执行的所有命令的效果:

BEGIN;
    INSERT INTO table1 VALUES (1);
    SAVEPOINT my_savepoint;
    INSERT INTO table1 VALUES (2);
    ROLLBACK TO SAVEPOINT my_savepoint;
    INSERT INTO table1 VALUES (3);
COMMIT;
Run Code Online (Sandbox Code Playgroud)

上述事务将插入值 1 和 3,但不会插入值 2。有关SAVEPOINT更多信息,请参阅文档。