如何确保只有一个过程副本在 Oracle 中运行?

rfu*_*sca 11 oracle oracle-11g-r2 plsql locking

我们需要确保只有一个特定过程的副本在 Oracle 中运行。如果它已经在运行并且用户试图打开另一个,那么它应该会出错。

这样做的最佳方法是什么?

Phi*_*lᵀᴹ 13

您可以使用DBMS_LOCK和 排他锁来做到这一点。

请参阅以下过程:

CREATE OR REPLACE PROCEDURE myproc
IS
  lockhandle VARCHAR2(128);
  retcode NUMBER;
BEGIN
  DBMS_LOCK.ALLOCATE_UNIQUE('myproclock',lockhandle);

  retcode:=DBMS_LOCK.REQUEST(lockhandle,timeout=>0, lockmode=>DBMS_LOCK.x_mode);

  IF retcode<>0
  THEN
    raise_application_error(-20000,'myproc is already running');
  END IF;

  /* sleep so that we can test with a 2nd execution */
  DBMS_LOCK.sleep(1000);

  retcode:=DBMS_LOCK.RELEASE(lockhandle);

END myproc;
/
Run Code Online (Sandbox Code Playgroud)

测试(会话 1):

SQL> BEGIN
  2  myproc();
  3  END;
  4  /
Run Code Online (Sandbox Code Playgroud)

(显然返回时DBMS_LOCK.sleep()返回)。

测试(会话 2):

SQL> BEGIN
  2  myproc();
  3  END;
  4  /
BEGIN
*
ERROR at line 1:
ORA-20000: myproc is already running
ORA-06512: at "PHIL.MYPROC", line 12
ORA-06512: at line 2


SQL>
Run Code Online (Sandbox Code Playgroud)

显然你需要GRANT EXECUTE ON DBMS_LOCK TO YOURUSER;