尝试使用嵌套事务控制执行过程时出现“错误:无效事务终止”

问题描述 投票:0回答:3

根据文档 (https://www.postgresql.org/docs/current/app-psql.html),即使

AUTOCOMMIT
设置为关闭,PSQL 也会在任何命令之前发出隐式
BEGIN
尚未在交易块中,并且本身不是
BEGIN
或其他交易控制命令,也不是无法在交易块内执行的命令,例如
VACUUM
。 (不幸的是,
CALL
的处理方式与
VACCUM
不同)。并且,根据 Shaun Thomas (https://blog.2ndquadrant.com/pg-phriday-stored-procedures-postgres-11/),无效交易终止错误的发生是因为无法关闭当前交易(在这种情况下,由 PSQL 启动)从过程中。我尝试了所有与事务控制相关的 PSQL 设置,但所有设置都出现无效事务终止错误;即使 PSQL 处理的命令文件只包含
CALL
语句。

这是我调用的程序:

create or replace procedure producto$cargar_imagenes(_super$ bigint, _archivo$ character varying) as $$
declare
    _msg character varying;
    _log rastro_proceso%ROWTYPE;
begin
    perform rastro_proceso_temporal$insert(_super$);
    perform producto$cargar_imagenes$biz(_super$, _archivo$);
    if (_super$ is not null and _super$ > 0) then
        perform producto$cargar_imagenes$log(_super$, _archivo$);
    else
        perform tarea_usuario$private$update(6519204281880642486, null);
    end if;
    commit;
end;
$$ language plpgsql set search_path = public;

commit
语句处失败;如果我将其注释掉,它就会起作用。

postgresql transactions plpgsql commit postgresql-11
3个回答
5
投票

删除

SET
条款。根据文档:

如果 SET 子句附加到过程,则该过程无法执行事务控制语句(例如,COMMIT 和 ROLLBACK,具体取决于语言)。


4
投票

如果在过程定义中包含“SECURITY DEFINER”子句,那么在 pg11(在版本 11.6 中测试)中,您似乎会遇到同样的问题。所以我猜 SECURITY DEFINER 有资格作为“SET”子句。

当我删除 SECURITY DEFINER 时,我可以在过程定义中包含一个 COMMIT 语句,而不会在 COMMIT 语句中出现 ERROR:invalid transaction termination。

不幸的是,这是一个运行时错误,而不是编译错误。


0
投票

我有一个类似的问题,其中过程将在 plpgsql 循环内处理更新,然后在提交更新后会抛出错误:“错误:无效事务终止”......最后尝试在 PG Admin 中打开 AutoCommit 并且过程有效。 .为了它的价值!

© www.soinside.com 2019 - 2024. All rights reserved.