Antworten:
Sie können dies mit DBMS_LOCK
und einem exklusiven Schloss tun .
Siehe das folgende Verfahren:
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 (Sitzung 1):
SQL> BEGIN
2 myproc();
3 END;
4 /
(Offensichtlich zurück, wenn DBMS_LOCK.sleep()
zurück).
Test (Sitzung 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>
Offensichtlich müssen Sie GRANT EXECUTE ON DBMS_LOCK TO YOURUSER;
.
Verwenden Sie eine Sperrtabelle.
Wenn die Prozedur beginnt, überprüfen Sie die Tabelle auf einen bekannten Wert. Wenn vorhanden, gehen Sie nicht weiter und beenden Sie proc. Wenn nicht, schreiben Sie den Wert in die Tabelle, führen Sie die Prozedur aus, löschen Sie den Wert und beenden Sie ihn wie gewohnt.
Wenn meine Kunden eine Anfrage mit einer einzigartigen Geschäftslogik wie dieser haben, versuche ich, die Frage umzudrehen und zu fragen, warum dies erforderlich ist.
Der beste Weg, um sicherzustellen, dass nur eine Kopie ausgeführt wird, besteht darin, die Benutzer die Prozedur überhaupt nicht ausführen zu lassen. Wenn dieses Verfahren so speziell ist, sollte seine Verwendung auf dba / Entwickler beschränkt sein.
Eine andere Möglichkeit besteht darin, diese Prozedur nur als Job auszuführen. Fügen Sie in der Prozedur eine Überprüfung hinzu, um festzustellen, ob Jobs ausgeführt werden, die dies aufrufen. Wenn dies der Fall ist, beenden Sie die weitere Verarbeitung und protokollieren Sie das Auftreten.