17 DBMS_ALERT

DBMS_ALERTは、データベース・イベント(アラート)の非同期通知をサポートします。このパッケージおよびデータベース・トリガーを適切に使用することで、アプリケーションは、データベース内で関連する値が変更されるたびに通知を受け取ることができます。

この章のトピックは、次のとおりです:

17.1 DBMS_ALERTの概要

このシナリオでは、DBMS_ALERTパッケージの可能な使用方法について説明します。

グラフィック・ツールで、データベース表のデータをグラフ表示する場合を想定します。グラフィック・ツールは、データを読み込んでグラフ表示した後、読み込んだデータに関連するデータベース・アラート(WAITONE)を待機できます。他のユーザーがデータを変更すると、ツールが自動的に起動されます。必要となるのは、データベース表にトリガーを設定することのみであり、この設定によって、トリガーが起動されると必ず信号(SIGNAL)が送信されます。

17.2 DBMS_ALERTのセキュリティ・モデル

このパッケージのセキュリティは、選択したユーザーまたはロールにこのパッケージのEXECUTE権限を付与することで制御できます。このパッケージの先頭部分に、使用するアラート名を制限するためのカバー・パッケージを記述することもできます。この場合は、パッケージではなく、このカバー・パッケージのEXECUTE権限を付与できます。

17.3 DBMS_ALERTの定数

DBMS_ALERTパッケージでは、このトピックで説明する定数が使用されます。

表17-1 DBMS_ALERTの定数

名前 タイプ 説明

MAXWAIT

INTEGER

86400000

アラートの最大待機時間です(1000日で、実質的には無期限)。

17.4 DBMS_ALERTの制限事項

データベース・アラートはコミットを発行するため、Oracle Formsでは使用できません。Oracle Formsがアクティブの状態でストアド・プロシージャをコールする場合の制限については、Oracle Formsのドキュメントを参照してください。

17.5 DBMS_ALERTの例外

DBMS_ALERTを使用すると、エラー状態のときにアプリケーション・エラー-20000が発生します。

表17-2に、エラー・メッセージおよびそのエラーが発生する可能性のあるプロシージャを示します。

17.6 DBMS_ALERTの操作上のノート

このトピックでは、一般アプリケーションおよび特定のアプリケーションに関するノートを示します。また、DBMS_ALERTエラー・メッセージのリストも示します。

  • アラートは、トランザクション単位で処理されます。つまり、アラートを通知するトランザクションがコミットされるまで、待機中セッションはアラートを受け取りません。したがって、特定のアラートに対する同時実行の送信と待機がいくつか発生する場合があります。

  • 待機中のアプリケーションはデータベース内でブロックされるため、別の処理は実行できません。

  • アプリケーションは、複数のイベントに対して登録でき、WAITANYプロシージャを使用して、すべてのイベントの発生を待機できます。

  • WAITONEまたはWAITANYプロシージャに対して、オプションのtimeoutパラメータを指定することもできます。timeoutを0(ゼロ)に設定すると、保留中のアラートが存在しない場合はすぐに戻されます。

  • 通知セッションは、待機中セッションが受け取るメッセージをオプションで渡せます。

  • アラートは、対応するアプリケーションの待機コールよりも頻繁に通知されます。この場合、古いアラートは廃棄されます。アプリケーションは、トランザクションのコミットごとに、最新のアラートを取得します。

  • アプリケーションで、トランザクション単位のアラートが必要ない場合は、DBMS_PIPEパッケージを使用してください。

    参照:

    DBMS_PIPE

  • SIGNALのコール後にトランザクションがロールバックされた場合、アラートは発生しません。

  • アラートを受け取り、データを読み込んでも、データが変更されていない場合があります。これは、先行したアラートの後にデータが変更されたが、その前に先行したアラートに関するデータが読み込まれているためです。

  • 通常、Oracleはイベント・ドリブンであるため、ポーリング・ループは発生しません。ポーリング・ループは、次の2つの場合に発生する可能性があります。

    • 共有モード。データベースを共有モードで実行している場合は、別のインスタンスからのアラートをチェックするためにポーリング・ループが必要です。ポーリング・ループのデフォルト値は1秒で、SET_DEFAULTSプロシージャで設定できます。

    • WAITANYプロシージャ。WAITANYプロシージャを使用していて、通知セッションが通知の1秒以内にコミットしない場合は、このコミットされていないアラートが別のアラートをカムフラージュしないようにするために、ポーリング・ループが必要です。ポーリング・ループは1秒間隔で始まり、30秒間隔まで段階的に変化します。

表17-2 DBMS_ALERTエラー・メッセージ

エラー・メッセージ プロシージャ

ORU-10001 lock request error, status: N

SIGNAL

ORU-10015 error: N waiting for pipe status

WAITANY

ORU-10016 error: N sending on pipe 'X'

SIGNAL

ORU-10017 error: N receiving on pipe 'X'

SIGNAL

ORU-10019 error: N on lock request

WAIT

ORU-10020 error: N on lock request

WAITANY

ORU-10021 lock request error; status: N

REGISTER

ORU-10022 lock request error, status: N

SIGNAL

ORU-10023 lock request error; status N

WAITONE

ORU-10024 there are no alerts registered

WAITANY

ORU-10025 lock request error; status N

REGISTER

ORU-10037 attempting to wait on uncommitted signal from same session

WAITONE

17.7 DBMS_ALERTの例

この例では、全従業員について、部門ごとの平均給与のグラフを作成するとします。アプリケーションは、EMPの変更を常に認識しておく必要があります。

アプリケーションのコードは次のようになります。

DBMS_ALERT.REGISTER('emp_table_alert');
    <<readagain>>: 
   /* ... read the emp table and graph it */ 
      DBMS_ALERT.WAITONE('emp_table_alert', :message, :status); 
      if status = 0 then goto <<readagain>>; else 
      /* ... error condition */ 

EMP表のトリガーは次のようになります。

CREATE TRIGGER emptrig AFTER INSERT OR UPDATE OR DELETE ON emp
    BEGIN 
      DBMS_ALERT.SIGNAL('emp_table_alert', 'message_text'); 
   END;

アラートが不要になると、アプリケーションは次の要求を作成します。

DBMS_ALERT.REMOVE('emp_table_alert');

この要求によって、アラートの通知側の処理量が削減されます。登録したアラートが存在している間にセッションが終了(または異常終了)した場合、そのアラートは結果的に、このパッケージの次のユーザーによって消去されます。

例では、アプリケーションが中間値をすべて参照するとはかぎりませんが、常に最新のデータを参照することが保証されます。

17.8 DBMS_ALERTサブプログラムの要約

この表は、DBMS_ALERTサブプログラムを示し、簡単に説明しています。

表17-3 DBMS_ALERTパッケージのサブプログラム

サブプログラム 説明

REGISTERプロシージャ

アラートからメッセージを受け取ります。

REMOVEプロシージャ

アラートからの通知を無効にします。

REMOVEALLプロシージャ

このセッションに対するアラートを登録リストからすべて削除します。

SET_DEFAULTSプロシージャ

ポーリング間隔を設定します。

SIGNALプロシージャ

アラートを通知します(登録セッションにメッセージを送信します)。

WAITANYプロシージャ

セッションに登録したアラートからのメッセージの受取りを、timeout秒待機します。

WAITONEプロシージャ

名前を設定したアラートからのメッセージの受取りを、timeout秒待機します。

17.8.1 REGISTERプロシージャ

セッションは、このプロシージャによってアラートを登録します。

構文

DBMS_ALERT.REGISTER (
   name      IN  VARCHAR2,
   cleanup   IN  BOOLEAN DEFAULT TRUE);

パラメータ

表17-4 REGISTERプロシージャのパラメータ

パラメータ 説明

name

このセッションに関連しているアラート名。

cleanup

DBMS_ALERTパッケージで使用される実在する孤立したパイプのクリーンアップを実行するかどうかを指定します。このクリーンアップは、パッケージのインスタンス化ごとにREGISTERへの最初のコールでのみ実行されます。パラメータのデフォルト値はTRUEです。

警告:

'ORA$'で始まるアラート名は、オラクル社の製品用に予約されています。アラート名は、30バイト以内で設定してください。名前では、大文字と小文字は区別されません。

使用上のノート

セッションは、必要な数のアラートを登録できます。アラートとの関連が不要になった場合は、REMOVEをコールしてそのアラートの登録を削除する必要があります。

17.8.2 REMOVEプロシージャ

アラートとの関連が不要になったセッションは、このプロシージャによって登録リストからそのアラートを削除できます。アラートを削除すると、アラートの通知側が行う処理量が削減されます。

構文

DBMS_ALERT.REMOVE (
   name  IN  VARCHAR2);

パラメータ

表17-5 REMOVEプロシージャのパラメータ

パラメータ 説明

name

登録リストから削除するアラート名(大/小文字区別なし)

使用上のノート

アラートの削除は、アラートの通知側が行う処理量を削減するための重要な処理です。セッションがアラートを削除せずに異常終了した場合、そのアラートは(即時ではありませんが)結果的に消去されます。

17.8.3 REMOVEALLプロシージャ

このプロシージャによって、このセッションに関連するアラートを登録リストからすべて削除します。セッションですべてのアラートが不要になったときは、必ずこのプロシージャを使用してください。

このプロシージャは、セッションの中でこのパッケージを初めて参照すると、自動的にコールされます。したがって、前のセッションが異常終了した場合でも、そのセッションに関連するアラートが現在のセッションに影響を与えることはありません。

このプロシージャは常にコミットを実行します。

構文

DBMS_ALERT.REMOVEALL;

17.8.4 SET_DEFAULTSプロシージャ

ポーリング・ループが必要な場合は、このSET_DEFAULTSプロシージャを使用してポーリング間隔を設定します。

構文

DBMS_ALERT.SET_DEFAULTS (
   sensitivity  IN  NUMBER);

パラメータ

表17-6 SET_DEFAULTSプロシージャのパラメータ

パラメータ 説明

sensitivity

ポール間でスリープするポーリング間隔(秒)。デフォルトは5秒です。

17.8.5 SIGNALプロシージャ

このプロシージャはアラートを通知します。SIGNALコールは、コールしたトランザクションがコミットされたときのみ有効になります。トランザクションがロールバックされると、SIGNALは無効になります。

このアラートを登録したすべてのセッションに通知されます。関連しているセッションが現在待機中の場合は、そのセッションが起動されます。関連しているセッションが現在待機中でない場合は、次にそのセッションが待機コールを行ったときに通知されます。

複数のセッションが、同時に同じアラートの通知を受けられます。各セッションは、アラートを通知するとき、コミットするまでその他の同時セッションをすべてブロックします。この結果、トランザクションはシリアル化されます。

構文

DBMS_ALERT.SIGNAL (
   name     IN  VARCHAR2,
   message  IN  VARCHAR2);

パラメータ

表17-7 SIGNALプロシージャのパラメータ

パラメータ 説明

name

通知するアラート名。

message

このアラートに関連付けるメッセージ(1800バイト以下)。

このメッセージが待機中のセッションに渡されます。待機中のセッションは、メッセージ内の情報を使用して、アラート発生後のデータベースの読込みを中止することもできます。

17.8.6 WAITANYプロシージャ

現行のセッションが登録されているすべてのアラートを対象として、そのいずれかの発生を待機する場合にこのプロシージャをコールします。

構文

DBMS_ALERT.WAITANY (
   name      OUT  VARCHAR2,
   message   OUT  VARCHAR2,
   status    OUT  INTEGER,
   timeout   IN   NUMBER DEFAULT MAXWAIT);

パラメータ

表17-8 WAITANYプロシージャのパラメータ

パラメータ 説明

name

発生したアラート名を戻します。

message

アラートに関連付けられたメッセージを戻します。

これは、SIGNALコールが提供するメッセージです。WAITANYの前に、このアラートで複数の通知が発生した場合は、最新のSIGNALコールに対応するメッセージが戻されます。それ以前のSIGNALコールのメッセージは廃棄されます。

status

戻される値:

0 - アラート発生。

1 - タイムアウト発生。

timeout

アラートの最大待機時間。

timeout秒以内にアラートが発生しない場合は、ステータス1が戻されます。

使用上のノート

このプロシージャが実行される前に、暗黙的なCOMMITが発行されます。アラートを待機する同じセッションが、最初にアラートを通知する場合もあります。この場合は、通知の後および待機の前にコミットする必要があり、この処理を行わないと、(DBMS_ALERTによってコールされる) DBMS_LOCK.REQUESTからステータス4が戻されます。

例外

-20000, ORU-10024: there are no alerts registered.

17.8.7 WAITONEプロシージャ

このプロシージャは、特定のアラートの発生を待機します。

このプロシージャが実行される前に、暗黙的なCOMMITが発行されます。最初にアラートを通知するセッションが、その後のトランザクションでアラートを待機する場合もあります。この場合は、通知の後および待機の前にコミットする必要があり、この処理を行わないと、(DBMS_ALERTによってコールされる) DBMS_LOCK.REQUESTからステータス4が戻されます。

構文

DBMS_ALERT.WAITONE (
   name      IN   VARCHAR2,
   message   OUT  VARCHAR2,
   status    OUT  INTEGER,
   timeout   IN   NUMBER DEFAULT MAXWAIT);

パラメータ

表17-9 WAITONEプロシージャのパラメータ

パラメータ 説明

name

待機するアラート名。

message

アラートに関連付けられたメッセージを戻します。

これは、SIGNALコールが提供するメッセージです。WAITONEの前に、このアラートで複数の通知が発生した場合は、最新のSIGNALコールに対応するメッセージが戻されます。それ以前のSIGNALコールのメッセージは廃棄されます。

status

戻される値:

0 - アラート発生。

1 - タイムアウト発生。

timeout

アラートの最大待機時間。

名前を設定したアラートがtimeout秒以内に発生しない場合は、ステータス1が戻されます。