Відповіді:
Це можна зробити 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;
.
Використовуйте таблицю "замок".
Коли процедура розпочнеться, перевірте таблицю на відоме значення, якщо присутні не переходите далі та вийдіть з проц. Якщо немає, запишіть значення в таблицю, виконайте процедуру, а потім видаліть значення та вийдіть як звичайне.
Коли у моїх клієнтів є запит із такою унікальною діловою логікою, як ця, я намагаюся перевернути питання і запитати, для чого це потрібно.
Найкращий спосіб переконатися, що працює лише одна копія - це не дати користувачам виконати процедуру взагалі. Якщо ця процедура настільки особлива, її використання слід обмежувати dba / developers.
Інший спосіб - запустити цю процедуру лише як роботу. Додайте в процедуру чек, щоб побачити, чи виконуються якісь завдання, що викликають це. Якщо вони потім припиняють подальшу обробку і записують подію.