Puede hacer esto con DBMS_LOCK
un bloqueo exclusivo.
Ver el siguiente procedimiento:
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;
/
Prueba (sesión 1):
SQL> BEGIN
2 myproc();
3 END;
4 /
(Obviamente regresa cuando DBMS_LOCK.sleep()
regresa).
Prueba (sesión 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>
Obviamente lo necesitas GRANT EXECUTE ON DBMS_LOCK TO YOURUSER;
.
Cuando mis clientes tienen una solicitud que tiene una lógica comercial única como esta, trato de dar vuelta la pregunta y preguntar por qué es necesaria.
La mejor manera de asegurarse de que solo se esté ejecutando una copia es no permitir que los usuarios ejecuten el procedimiento. Si este procedimiento es tan especial, entonces su uso debe restringirse a dba / developers.
Otra forma es ejecutar este procedimiento solo como un trabajo. Agregue una comprobación en el procedimiento para ver si se están ejecutando trabajos que lo llaman. Si lo están, detenga el procesamiento adicional y registre la aparición.
fuente