Oracleでは、特定のプロシージャのコピーが1つだけ実行されていることを確認する必要があります。それがすでに実行されていて、ユーザーが別のものを開こうとすると、エラーになります。
これを行う最良の方法は何ですか?
_DBMS_LOCK
_と排他ロックを使用してこれを行うことができます。
次の手順を参照してください。
_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;
/
_
テスト(セッション1):
_SQL> BEGIN
2 myproc();
3 END;
4 /
_
(明らかにDBMS_LOCK.sleep()
が戻ると戻ります)。
テスト(セッション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>
_
明らかに_GRANT EXECUTE ON DBMS_LOCK TO YOURUSER;
_が必要です。
「ロック」テーブルを使用します。
プロシージャが開始したら、テーブルに既知の値があるかどうかを確認します。存在する場合は、それ以上進んでprocを終了します。存在しない場合は、値をテーブルに書き込み、プロシージャを実行してから、値を削除して通常どおり終了します。
私のクライアントがこのようなユニークなビジネスロジックを持つリクエストを持っている場合、私は質問を変えて、なぜこれが必要なのか尋ねます。
1つのコピーのみが実行されていることを確認する最良の方法は、ユーザーがプロシージャをまったく実行できないようにすることです。この手順が特別な場合は、その使用をdba/developersに制限する必要があります。
別の方法は、このプロシージャをジョブとしてのみ実行することです。手順にチェックを追加して、これを呼び出すジョブが実行されているかどうかを確認します。その後、処理を停止し、発生をログに記録します。