根据文档 (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
语句处失败;如果我将其注释掉,它就会起作用。
如果在过程定义中包含“SECURITY DEFINER”子句,那么在 pg11(在版本 11.6 中测试)中,您似乎会遇到同样的问题。所以我猜 SECURITY DEFINER 有资格作为“SET”子句。
当我删除 SECURITY DEFINER 时,我可以在过程定义中包含一个 COMMIT 语句,而不会在 COMMIT 语句中出现 ERROR:invalid transaction termination。
不幸的是,这是一个运行时错误,而不是编译错误。
我有一个类似的问题,其中过程将在 plpgsql 循环内处理更新,然后在提交更新后会抛出错误:“错误:无效事务终止”......最后尝试在 PG Admin 中打开 AutoCommit 并且过程有效。 .为了它的价值!