您可以创建一个表processes。您还可以确保每个进程都有某种唯一标识符——例如来自dba_objects 的owner, object_name 的散列,因此您可以在包中动态创建它。
然后,您可以在进程运行时为lock each row individually 创建一个函数。
正如@Sergio 在 cmets 中指出的那样,如果由于某种原因您需要在流程中间提交,这将不起作用 - 当然,除非您在每次提交后重新选择。
function locking ( Pid ) return number is
l_locked number := 0;
begin
select 1
into l_locked
from processes
where id = Pid
-- exit immediately if the proc is running
for update nowait
;
return l_locked;
exception when others then
return 0;
end;
这样做的好处是为您锁定processes 中的该行,直到当前正在运行您的过程的会话完成。
然后将其包装在您的过程中:
-- if we failed to lock locking will have thrown an error
-- i.e. we have 0 here.
if locking( 123 ) = 0 then
exit;
end if;
只要每个过程都有一个唯一的 id - 重要的一点 - 你的过程就会干净地退出。
它可能不适用于您的情况,但我通常的做法是使用mod。尽管它不会停止同一进程的 2 个运行,但它确实确保当您有超过 1 个时,您只能在不同的数据上运行它们。如下所示:
procedure my_procedure ( PNumerator number, PDenominator number ) is
cursor c_my_cursor ( CNumerator number, CDenominator number ) is
select columns
from my_table
where mod( ascii(substr(id, -1)), CDenominator ) = CNumerator
;
begin
open c_my_cursor( PNumerator, PDenominator );
...
end;