Ответы:
Вы можете сделать это с 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;
/
Тест (сессия 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>
Очевидно, вам нужно GRANT EXECUTE ON DBMS_LOCK TO YOURUSER;
.
Используйте таблицу блокировки.
Когда процедура начинается, проверьте в таблице известное значение, если оно присутствует, не переходите дальше и выходите из proc. Если нет, запишите значение в таблицу, выполните процедуру, затем удалите значение и выйдите как обычно.
Когда у моих клиентов появляется запрос с уникальной бизнес-логикой, такой как этот, я пытаюсь перевернуть вопрос и спросить, зачем это нужно.
Лучший способ убедиться, что запущена только одна копия, - не дать пользователям вообще выполнить процедуру. Если эта процедура настолько особенная, то ее использование должно быть ограничено dba / developers.
Другой способ - запустить эту процедуру только как задание. Добавьте проверку в процедуру, чтобы увидеть, выполняются ли какие-либо задания, вызывающие это. Если это так, остановите дальнейшую обработку и зарегистрируйте вхождение.