Réponses:
Vous pouvez le faire avec DBMS_LOCK
et un verrou exclusif.
Voir la procédure suivante:
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 (session 1):
SQL> BEGIN
2 myproc();
3 END;
4 /
(Retourne évidemment au DBMS_LOCK.sleep()
retour).
Test (session 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>
De toute évidence, vous devez GRANT EXECUTE ON DBMS_LOCK TO YOURUSER;
.
Utilisez une table «verrouillée».
Lorsque la procédure démarre, vérifiez la table pour une valeur connue, si elle est présente, n'allez pas plus loin et quittez proc. Sinon, écrivez la valeur dans la table, exécutez la procédure, puis supprimez la valeur et quittez normalement.
Lorsque mes clients ont une demande qui a une logique métier unique comme celle-ci, j'essaie de tourner la question et de demander pourquoi cela est nécessaire.
Le meilleur moyen de s'assurer qu'une seule copie est en cours d'exécution est de ne pas laisser les utilisateurs exécuter la procédure. Si cette procédure est si spéciale, son utilisation doit être réservée aux dba / développeurs.
Une autre façon consiste à exécuter uniquement cette procédure en tant que travail. Ajoutez une vérification dans la procédure pour voir si des travaux qui l'appellent sont en cours d'exécution. S'ils le sont, arrêtez le traitement et enregistrez l'occurrence.