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

时间:2018-11-08 19:21:20

标签: postgresql transactions plpgsql commit postgresql-11

根据文档(https://www.postgresql.org/docs/current/app-psql.html),即使将AUTOCOMMIT设置为off,PSQL也会在任何尚未在事务块中且不在事务块中的命令之前发出隐式BEGIN本身是BEGIN或其他事务控制命令,也不是不能在事务块内执行的命令,例如VACUUM。 (不幸的是,CALLVACCUM的处理方式不同)。而且,根据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语句中失败;如果我将其注释掉,它将起作用。

2 个答案:

答案 0 :(得分:2)

删除SET子句。每个the documentation:

  

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

答案 1 :(得分:1)

如果在过程定义中包含“ SECURITY DEFINER”子句,似乎在pg11(在11.6版中进行了测试)中存在相同的问题。因此,我认为SECURITY DEFINER可以视为“ SET”子句。

当我删除SECURITY DEFINER时,我可以在过程定义中包括COMMIT语句,而不会出现ERROR:COMMIT语句上无效的事务终止。

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