web-dev-qa-db-ja.com

プロシージャのコピーが1つだけOracleで実行されていることをどのように確認できますか?

Oracleでは、特定のプロシージャのコピーが1つだけ実行されていることを確認する必要があります。それがすでに実行されていて、ユーザーが別のものを開こうとすると、エラーになります。

これを行う最良の方法は何ですか?

10
rfusca

_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;_が必要です。

12
Philᵀᴹ

「ロック」テーブルを使用します。

プロシージャが開始したら、テーブルに既知の値があるかどうかを確認します。存在する場合は、それ以上進んでprocを終了します。存在しない場合は、値をテーブルに書き込み、プロシージャを実行してから、値を削除して通常どおり終了します。

2
Stuart Moore

私のクライアントがこのようなユニークなビジネスロジックを持つリクエストを持っている場合、私は質問を変えて、なぜこれが必要なのか尋ねます。

1つのコピーのみが実行されていることを確認する最良の方法は、ユーザーがプロシージャをまったく実行できないようにすることです。この手順が特別な場合は、その使用をdba/developersに制限する必要があります。

別の方法は、このプロシージャをジョブとしてのみ実行することです。手順にチェックを追加して、これを呼び出すジョブが実行されているかどうかを確認します。その後、処理を停止し、発生をログに記録します。

1
kevinsky