Odpowiedzi:
Możesz to zrobić za DBMS_LOCK
pomocą specjalnej blokady.
Zobacz następującą procedurę:
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;
/
Test (sesja 1):
SQL> BEGIN
2 myproc();
3 END;
4 /
(Oczywiście wraca, gdy DBMS_LOCK.sleep()
wraca).
Test (sesja 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>
Oczywiście, że musisz GRANT EXECUTE ON DBMS_LOCK TO YOURUSER;
.
Użyj tabeli „blokady”.
Gdy procedura się rozpocznie, sprawdź tabelę pod kątem znanej wartości, jeśli jest dostępna, nie idź dalej i wyjdź z proc. Jeśli nie, zapisz wartość do tabeli, wykonaj procedurę, następnie usuń wartość i wyjdź jak zwykle.
Kiedy moi klienci mają żądanie, które ma unikalną logikę biznesową taką jak ta, staram się odwrócić pytanie i zapytać, dlaczego jest to potrzebne.
Najlepszym sposobem, aby upewnić się, że tylko jedna kopia jest uruchomiona, jest w ogóle nie pozwolić użytkownikom na wykonanie procedury. Jeśli ta procedura jest tak wyjątkowa, to jej użycie powinno być ograniczone do dba / deweloperów.
Innym sposobem jest uruchomienie tej procedury tylko jako zadanie. Dodaj zaznaczenie w procedurze, aby sprawdzić, czy uruchomione są jakiekolwiek zadania wywołujące to. Jeśli tak, zatrzymaj dalsze przetwarzanie i zapisz zdarzenie.