当前位置: 首页 > 知识库问答 >
问题:

Postgres支持嵌套事务还是自治事务?

熊烨
2023-03-14

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

CREATE TABLE subtransaction_tbl
(
  entryval integer
)

以及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;

第一种情况:

BEGIN TRANSACTION;
INSERT INTO subtransaction_tbl VALUES (4);
select  subtransaction_nested_test_t();
COMMIT TRANSACTION;

表中的条目正确:1、2、4

第二种情况:

BEGIN TRANSACTION;
INSERT INTO subtransaction_tbl VALUES (4);
select  subtransaction_nested_test_t();
ROLLBACK TRANSACTION;

表中的值未填充

我希望12应该添加到表 中,但出乎意料的是没有插入任何值。我想象函数打开了一个新的子事务,它不应该依赖于父事务。如果我是对的,请告诉我。

Postgres中是否存在自主交易?或者我必须修改我的plpython3u函数吗?

共有2个答案

闻人献
2023-03-14

在Postgres 11之前的Postgres中没有自治事务,在Postgres 11中添加了SQL过程。函数中所做的一切都随事务一起回滚。

以下是对该功能的讨论:

  • http://wiki.postgresql.org/wiki/Autonomous_subtransactions

在Postgres 10或更早版本中,一种解决方法是(ab-)使用dblink:

  • dblink无法在UPDATE触发器后更新同一数据库上的表
  • 如何在PostgreSQL中进行大型非阻塞更新?

还有相关的< code >保存点概念。(不是一回事!):

plpython有子事务(withplpy.subtransaction():),但这与自主事务不同。没有单独的COMMIT。它所做的就是将几个语句捆绑在一起,使它们成为原子。没有它,如果中间某个地方发生异常,并且您捕获了该异常,则只会执行该异常之前的代码。如果您将其包装到子事务中,则要么全部要么没有。这就像使用SAVEPOINT,而不是自主事务。每个留档:

子事务上下文管理器不捕获错误,它只确保在其作用域内执行的所有数据库操作将被自动提交或回滚。

萧琛
2023-03-14

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

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

  • SAVEPOINT name-创建一个新的保存点,名称为事务唯一
  • RELEASE SAVEPOINT name-提交保存点,尽管只有在包含事务提交
  • 时它才会持续存在
  • ROLLBACK TO SAVEPOINT name-回滚保存点

您还必须确保:

    < li >用于每个< code >保存点的名称是唯一的; < li >一个< code >保存点中的故障会向上传播到顶层。

最后一点有点棘手,除非你使用一个可以自动完成这项工作的库。

当我写pg-promise时,我确保这两个条款得到保证:

    < li >根据交易级别自动生成保存点名称,如< code>level_1、< code>level_2等; < li >它执行时包含< code > roll back TO save point name ,以及在子事务失败时的顶级< code>ROLLBACK,所有这些都建立在标准的promise链逻辑上。

另请参阅PostgreSQL嵌套事务的限制解释…

 类似资料:
  • 据我所知,当您尝试在提交前一个事务之前开始一个事务时,会发生这种异常。然而,我不明白为什么在我的情况下会有这种例外。 我有一个Web应用程序与以下servlet: 这是我的Compte对象: 这是我的DAO的接口: 这就是它的实施: 另外,这是我的Spring配置: 关联的应用程序。属性文件包含以下行: 最后,我有以下servlet过滤器,从这里开始事务: 这是在网络上映射的。如下所示的xml文件

  • 问题内容: JTA为什么不支持嵌套事务?是因为实现它们的复杂性(我对此表示怀疑)还是某些设计原则? 问题答案: (正如@Piotr Nowicki指出的那样,JTA 确实 允许嵌套事务,但这不是强制性的可选操作。) 为什么?这是无法确定地回答的问题之一,除非您是做出决定时“在房间里”的人之一。 将嵌套事务作为规范的一部分包括在内可能是固有的复杂性。或当时明显的复杂性;即他们不知道他们知道如何做一个

  • 问题内容: 我需要确保许多并发用户能够访问数据库。虽然在每次提交后我都关闭了会话,但是有时我的代码遇到以下错误,但是当我几次执行相同的操作时,它会超过错误并可以正常工作。 我的hibernate状态是4.2.1。 我的密码 HibernateUtil 组态 问题答案: 在您的“我的代码”代码段中,可能存在一些问题: 发生异常时,没有阻止关闭会话的块 您正在打电话,但这与有所不同。因此,不会清除。

  • 我们继续上一章节的内容,大家应该记得我们 Lua 代码中是如何完成 ngx_postgres 模块调用的。我们把他简单改造一下,让他更接近真实代码。 local json = require "cjson" function db_exec(sql_str) local res = ngx.location.capture('/postgres',

  • 环境: 我们有一个应用程序部署在 JBoss 4.2.3.GA 服务器中,它使用Hibernate 3.4 和 JTA 1.0。 有一个导入器创建或更新某些实体,然后导入一些数据。由于多种原因,大部分导入是在新事务中完成的,在每个事务中,在外部事务中创建/更新的实体可能会再次更新。 调用序列类似于以下伪代码: 服务1: 服务2: 问题: 现在的问题是,我们最终会遇到一个竞争条件,有几个事务试图锁定

  • 问题内容: 运行removeUserFromConference方法时,遇到以下异常: 道方法: 模型类: 问题答案: 您可能已经开始了一笔交易,并尝试开始另一笔交易而没有提交或回滚上一笔交易。使用程序化事务划分时的惯用法如下: 这很麻烦且容易出错,这就是为什么使用EJB或Spring具有声明式事务如此有用的原因之一。