↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11
历史版本PostgreSQL 13 已于 2025 年 11 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

42.8. 事务管理 #

在由 CALL 命令调用的过程中,以及在匿名代码块(DO 命令)中,可以使用 COMMIT 和 ROLLBACK 结束事务。事务通过这些命令结束后,会自动开始一个新事务,因此不存在单独的 START TRANSACTION 命令(注意 BEGIN 和 END 在 PL/pgSQL 中含义不同)。

这里是一个简单的示例:

CREATE PROCEDURE transaction_test1()
LANGUAGE plpgsql
AS $$
BEGIN
    FOR i IN 0..9 LOOP
        INSERT INTO test1 (a) VALUES (i);
        IF i % 2 = 0 THEN
            COMMIT;
        ELSE
            ROLLBACK;
        END IF;
    END LOOP;
END;
$$;

CALL transaction_test1();

新事务开始时具有默认事务特征,如事务隔离级别。在循环中提交事务的情况下,可能需要以与前一个事务相同的特征来自动启动新事务。命令 COMMIT AND CHAIN 和 ROLLBACK AND CHAIN 可以完成此操作。

只有在从顶层调用的 CALL 或 DO 中才能进行事务控制,在没有任何其他中间命令的嵌套 CALL 或 DO 调用中也能进行事务控制。例如,如果调用栈是 CALL proc1() → CALL proc2() → CALL proc3(),那么第二个和第三个过程可以执行事务控制动作。但是如果调用栈是 CALL proc1() → SELECT func2() → CALL proc3(),则最后一个过程不能做事务控制,因为中间有 SELECT。

游标循环需要特别考虑。来看这个例子:

CREATE PROCEDURE transaction_test2()
LANGUAGE plpgsql
AS $$
DECLARE
    r RECORD;
BEGIN
    FOR r IN SELECT * FROM test2 ORDER BY x LOOP
        INSERT INTO test1 (a) VALUES (r.x);
        COMMIT;
    END LOOP;
END;
$$;

CALL transaction_test2();

通常,游标会在事务提交时自动关闭。但是,在这样的循环中创建的游标,会自动转换为可保持游标,转换发生于第一次 COMMIT 或 ROLLBACK。这意味着,游标将在第一次执行以下命令时被完整求值:COMMIT 或 ROLLBACK,而不是逐行求值。循环结束后游标仍然会被自动移除,因此这些行为对用户大多是不可见的。

由非只读命令(例如 UPDATE ... RETURNING)驱动的游标循环中,不允许使用事务命令。

不能在带有异常处理器的块中结束事务。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。