嵌套存储过程的增量进展(Postgres)
Incremental progress on nested stored procedure (Postgres)
我有三个按顺序 运行 的 Postgres 存储过程(即 SP1 将调用 SP2,然后调用 SP3)。在处理这些嵌套存储过程时,我注意到只有在最后一个存储过程完成 (SP3) 之后我才能看到 SP1 的结果。
有没有办法在执行时产生这些过程的结果,而不是等待所有过程完成?
谢谢!
部分代码供参考:
create or replace procedure sp1()
as $$
declare
begin
drop table if exists seq_test;
create table seq_test (
step varchar,
status varchar,
time_log timestamp not null default now()
);
insert into seq_test values ('1','running','now');
raise notice 'step 1 beginning';
-- does something
insert into seq_test values ('1','complete','now');
raise notice 'step 1 complete';
call sp2();
end;
$$
language plpgsql;
--------------
create or replace procedure sp2()
as $$
declare
begin
insert into seq_test values ('2','running','now');
raise notice 'step 2 beginning';
-- does something else
insert into seq_test values ('2','complete','now');
raise notice 'step 2 complete';
call sp3();
end;
$$
language plpgsql;
--------------
create or replace procedure sp3()
as $$
declare
begin
insert into seq_test values ('3','running','now');
raise notice 'step 3 beginning';
-- does something else
insert into seq_test values ('3','complete','now');
raise notice 'step 3 complete';
end;
$$
language plpgsql;
--------------------------------------------------
call sp1();
在上面的脚本中,如果假设每个 SP 需要 1 分钟才能完成,尽管在整个 3 分钟的运行时间中记录被插入 seq_test 我实际上不会能够观察到这些记录,直到每个SP都完成。
您看不到结果,因为数据修改只有在进行修改的事务结束后才可见。这是由默认的 READ COMMITTED
事务隔离级别保证的,在 PostgreSQL 中没有办法获得“脏读”。
默认情况下,CALL sp1()
将在单个事务中 运行,这解释了您观察到的情况。
您可以通过在存储过程中显式调用 COMMIT AND CHAIN
来更改该行为。这将提交到目前为止的工作并开始一个新的事务。但考虑后果:如果执行遇到错误,事务将被回滚(撤销)。程序中间的 COMMIT
可能导致只完成部分工作。这可能正是您所需要的,但通常是不希望的。
我有三个按顺序 运行 的 Postgres 存储过程(即 SP1 将调用 SP2,然后调用 SP3)。在处理这些嵌套存储过程时,我注意到只有在最后一个存储过程完成 (SP3) 之后我才能看到 SP1 的结果。
有没有办法在执行时产生这些过程的结果,而不是等待所有过程完成?
谢谢!
部分代码供参考:
create or replace procedure sp1()
as $$
declare
begin
drop table if exists seq_test;
create table seq_test (
step varchar,
status varchar,
time_log timestamp not null default now()
);
insert into seq_test values ('1','running','now');
raise notice 'step 1 beginning';
-- does something
insert into seq_test values ('1','complete','now');
raise notice 'step 1 complete';
call sp2();
end;
$$
language plpgsql;
--------------
create or replace procedure sp2()
as $$
declare
begin
insert into seq_test values ('2','running','now');
raise notice 'step 2 beginning';
-- does something else
insert into seq_test values ('2','complete','now');
raise notice 'step 2 complete';
call sp3();
end;
$$
language plpgsql;
--------------
create or replace procedure sp3()
as $$
declare
begin
insert into seq_test values ('3','running','now');
raise notice 'step 3 beginning';
-- does something else
insert into seq_test values ('3','complete','now');
raise notice 'step 3 complete';
end;
$$
language plpgsql;
--------------------------------------------------
call sp1();
在上面的脚本中,如果假设每个 SP 需要 1 分钟才能完成,尽管在整个 3 分钟的运行时间中记录被插入 seq_test 我实际上不会能够观察到这些记录,直到每个SP都完成。
您看不到结果,因为数据修改只有在进行修改的事务结束后才可见。这是由默认的 READ COMMITTED
事务隔离级别保证的,在 PostgreSQL 中没有办法获得“脏读”。
默认情况下,CALL sp1()
将在单个事务中 运行,这解释了您观察到的情况。
您可以通过在存储过程中显式调用 COMMIT AND CHAIN
来更改该行为。这将提交到目前为止的工作并开始一个新的事务。但考虑后果:如果执行遇到错误,事务将被回滚(撤销)。程序中间的 COMMIT
可能导致只完成部分工作。这可能正是您所需要的,但通常是不希望的。