交易中的交易


18

如果例如以下脚本被调用,PostgreSQL将显示什么行为?

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

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

Answers:


13

您将需要一个所谓的“自主事务”(oracle提供的功能)。目前,这在PostgreSQL中还不可能。但是,您可以使用SAVEPOINT

BEGIN;
INSERT ...
SAVEPOINT a;
some error;
ROLLBACK TO SAVEPOINT a;
COMMIT;

它不完全是一个自主交易,但是,它使您能够正确地进行“每笔交易”。您可以使用它来实现您对自动交易的期望。

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


13

您可以自己尝试:

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

它不会启动新的(子)事务,因为PostgreSQL中未实现嵌套事务。(不过,您可以在pl/pgsql函数中做一些魔术,例如,模仿该行为。)

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

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


9

PostgreSQL不支持子事务,但是该SAVEPOINT功能可以有效地满足您的需求。从用于文档引用通过用先进接入层PG维塔利Tomilov GitHub上:

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;

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.