Postgres是否支持嵌套或自治事务?

Sar*_*hAk 17 sql postgresql transactions python-3.x

我有一种情况,我必须提交一部分代码作为自己的事务.
我创建了一个表subtransaction_tbl:

CREATE TABLE subtransaction_tbl
(
  entryval integer
)
Run Code Online (Sandbox Code Playgroud)

和语言plpython3u中的函数:

CREATE FUNCTION subtransaction_nested_test_t() RETURNS void
AS $$
plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
with plpy.subtransaction():
    plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
$$ LANGUAGE plpython3u;
Run Code Online (Sandbox Code Playgroud)

第一种情况:

BEGIN TRANSACTION;
INSERT INTO subtransaction_tbl VALUES (4);
select  subtransaction_nested_test_t();
COMMIT TRANSACTION;
Run Code Online (Sandbox Code Playgroud)

表中的条目是正确的:1,2,4

第二种情况:

BEGIN TRANSACTION;
INSERT INTO subtransaction_tbl VALUES (4);
select  subtransaction_nested_test_t();
ROLLBACK TRANSACTION;
Run Code Online (Sandbox Code Playgroud)

表中的值未填充

我预计12应该添加到表中,subtransaction_tbl但令我惊讶的是没有插入任何值.我想象一个新的子事务由函数打开,它不应该依赖于父事务.如果我是对的,请告诉我.

Postgres有自动交易吗?或者我是否必须修改我的plpython3u函数?

vit*_*y-t 19

Postgres确实支持嵌套事务,但它们与传统SQL不同,更像是具有嵌套部分点的事务.

在顶层,您始终拥有典型的BEGIN/COMMIT/ROLLBACK,在嵌套级别上,您必须使用以下命令:

  • SAVEPOINT name - 创建一个新的保存点,其名称对于事务是唯一的
  • RELEASE SAVEPOINT name - 提交保存点,但只有在包含事务提交时才会保留
  • ROLLBACK TO SAVEPOINT name - 回滚保存点

您还必须确保:

  • 每个名称SAVEPOINT都是唯一的;
  • 一个中的失败SAVEPOINT向上传播到顶层.

最后一点有点棘手,除非您使用可以自动为您执行此操作的库.

当我写pg-promise时,我确保这两项规定得到保证:

  • 它根据事务级别自动生成保存点名称,as level_1,level_2等等;
  • 它执行包含ROLLBACK TO SAVEPOINT name,以及在ROLLBACK子事务失败的情况下的顶级- 所有这些都构建在标准的promise-chaining逻辑上.

另请参阅解释的PostgreSQL嵌套事务的局限性 ......

  • 这不是**嵌套事务,因为当你回滚外部事务时,**所有**都将被回滚.对嵌套事务的共同理解意味着即使在回滚"外部"事务时也可以提交它. (8认同)
  • @a_horse_with_no_name,是的,这是非常规部分,不幸的是,在顶层调用“rollback”将恢复任何嵌套“savepoint”的更改。这就是正确的嵌套事务和通过保存点嵌套事务之间的区别。 (4认同)
  • 你能用"非常规"澄清你的意思吗(你能给我一些参考资料吗?),这是我第一次研究嵌套交易.从开发人员的角度来看,我希望事务上的`rollback`能够回滚其中发生的任何事情,无论是简单的查询还是子事务(无论它们是否被提交).您使用"保存点"描述的行为似乎更有意义. (3认同)
  • 让我感到困惑的是“**成功的子事务** [...] 的结果”,因为这是 Postgres 文档未定义的概念。`开始;Q1; 开始; Q2;犯罪; ROLLBACK;` 等价于 `BEGIN; Q1; /* 警告; */ Q2;犯罪; /* 警告; */`。对我来说,它不是“子事务的参考行为”,而是无声错误和缺乏对一流嵌套事务的支持的说明。这是您所说的“常规 SQL”,还是您指的是其他声称支持嵌套事务但仍按您描述的方式运行的 SQL 实现? (2认同)

Erw*_*ter 18

Postgres 中没有自动交易,包括Postgres 9.4.在该函数中完成的所有操作都将与事务一起回滚.

项目列表中有一个打开的TODO项:

以下是对该功能的讨论:

目前,解决方法可能是(ab-)使用dblink:

还有一个相关的概念SAVEPOINT.(不一样!):

plpython

plpython有subtransactions(with plpy.subtransaction():),但这与自治事务不同.没有单独的COMMIT.它所做的只是将几个语句捆绑在一起,使它们成为原子.如果没有它,如果异常发生在中间某处,并且您捕获该异常,则只会执行此异常的代码.如果将它包装成子事务,则全部或全部.这就像使用a SAVEPOINT,而不是自治事务.每个文件:

子事务上下文管理器不会捕获错误,它只确保在其作用域内执行的所有数据库操作都将以原子方式提交或回滚.