【问题标题】:Is there a best way to avoid execution of process more than once in Oracle?是否有避免在 Oracle 中多次执行进程的最佳方法?
【发布时间】:2012-04-07 04:12:49
【问题描述】:

假设我有一个名为myprocprocedure。这是一个复杂的过程,我不能允许两个实例同时执行 proc。

实际上我使用dbms_application_info.set_module

procedure start_process is
begin
  dbms_application_info.set_module('myproc', 'running');
end;

并在运行该过程之前进行验证:

select 'S'
  from v$session v
 where v.module = 'myproc'
   and v.action = 'running';

在数据库级别,有没有更好的方法来检查这个?

【问题讨论】:

标签: oracle plsql


【解决方案1】:

dbms_lock.allocate_uniquedbms_lock.request 一起使用。 使用说明说:

第一个使用新锁名调用 ALLOCATE_UNIQUE 的会话会导致 要生成并存储在 dbms_lock_allocated 表中的唯一锁 ID。 后续调用(通常由其他会话)返回之前生成的锁 ID。

我想这可能就是你所追求的。

【讨论】:

  • +1,这比我的想法好得多...我已经习惯了在收集大量元数据的同时做其他事情。
  • 真正有趣的功能。谢谢!
【解决方案2】:

您可以创建一个表processes。您还可以确保每个进程都有某种唯一标识符——例如来自dba_objectsowner, 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;

【讨论】:

  • 如果您出于某种原因需要在过程中间提交,这会破坏,对吧?
猜你喜欢
  • 2015-06-12
  • 2010-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-23
相关资源
最近更新 更多