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;
/
测试(会话 1):
SQL> BEGIN
2 myproc();
3 END;
4 /
(显然返回时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>
您可以
DBMS_LOCK
使用独占锁来执行此操作。请参阅以下过程:
测试(会话 1):
(显然返回时
DBMS_LOCK.sleep()
返回)。测试(会话 2):
显然你需要
GRANT EXECUTE ON DBMS_LOCK TO YOURUSER;
。使用“锁定”表。
当程序启动时,检查表中是否存在已知值,如果存在则不要继续并退出 proc。如果不存在,将值写入表,执行过程,然后删除值并正常退出。
当我的客户有一个像这样的具有独特业务逻辑的请求时,我会尝试扭转问题并询问为什么需要这样做。
确保只有一个副本正在运行的最佳方法是根本不让用户执行该过程。如果这个过程非常特殊,那么它的使用应该仅限于 dba/developers。
另一种方法是仅将此过程作为作业运行。在过程中添加一个检查以查看是否有任何调用它的作业正在运行。如果他们停止进一步处理并记录发生的情况。