Risposte:
Puoi farlo con DBMS_LOCK
un lucchetto esclusivo.
Vedi la seguente procedura:
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 (sessione 1):
SQL> BEGIN
2 myproc();
3 END;
4 /
(Ovviamente ritorna quando DBMS_LOCK.sleep()
ritorna).
Test (sessione 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>
Ovviamente è necessario GRANT EXECUTE ON DBMS_LOCK TO YOURUSER;
.
Utilizzare una tabella di "blocco".
All'avvio della procedura controllare la tabella per un valore noto, se presente non andare oltre e uscire da proc. In caso contrario, scrivere il valore nella tabella, eseguire la procedura, quindi eliminare il valore ed uscire normalmente.
Quando i miei clienti hanno una richiesta con una logica aziendale unica come questa, provo a invertire la domanda e chiedermi perché sia necessario.
Il modo migliore per assicurarsi che sia in esecuzione una sola copia è di non consentire agli utenti di eseguire la procedura. Se questa procedura è così speciale, il suo utilizzo dovrebbe essere limitato a dba / developers.
Un altro modo è eseguire questa procedura solo come lavoro. Aggiungere un segno di spunta nella procedura per vedere se sono in esecuzione lavori che lo chiamano. In tal caso, interrompere ulteriormente l'elaborazione e registrare l'occorrenza.