ヘッダーをスキップ
Oracle® Databaseアドバンスト・アプリケーション開発者ガイド
11gリリース2 (11.2)
B56259-09
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

11 連続問合せ通知(CQN)の使用

連続問合せ通知(CQN)を使用すると、問合せをオブジェクト変更通知用(デフォルト)または問合せ結果変更通知用としてアプリケーションからデータベースに登録できます。登録済の問合せで参照されるオブジェクトは、登録済オブジェクトです。

オブジェクト変更通知(OCN)に対する問合せが登録されると、その問合せで参照されるオブジェクトがトランザクションによって変更されてコミットされるたびに、問合せ結果が変更されたかどうかにかかわらず、データベースからアプリケーションに通知されます。

問合せ結果変更通知(QRCN)に対して問合せが登録されると、その問合せの結果がトランザクションによって変更されてコミットされるたびに、データベースからアプリケーションに通知されます。

CQN登録により、1つ以上の問合せのリストが通知タイプ(OCNまたはQRCN)および通知ハンドラに関連付けられます。CQN登録を作成するには、PL/SQLインタフェースまたはOracle Call Interface(OCI)を使用できます。PL/SQLインタフェースを使用する場合、通知ハンドラはサーバー側のPL/SQLストアド・プロシージャになり、OCIを使用する場合、通知ハンドラはクライアント側のCコールバック・プロシージャになります。

この章では、CQNの一般的な概念と、PL/SQL CQNインタフェースの使用方法について説明します。CQNにOCIを使用する方法の詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』を参照してください。

内容は次のとおりです。


注意:

OCNおよびQRCNという用語は、通知タイプと通知自体の両方を指します。アプリケーションによりOCNに対する問合せが登録されると、データベースからアプリケーションにOCNが送信され、アプリケーションによりQRCNに対する問合せが登録されると、データベースからアプリケーションにQRCNが送信されます。

オブジェクト変更通知(OCN)

アプリケーションでオブジェクト変更通知(OCN)に対する問合せが登録されると、その問合せに関連付けられているオブジェクトがトランザクションによって変更されてコミットされるたびに、問合せ結果が変更されたかどうかにかかわらず、データベースからアプリケーションにOCNが送信されます。

たとえば、アプリケーションで例11-1のOCNに対する問合せが登録され、EMPLOYEES表を変更するトランザクションがユーザーによってコミットされると、変更された行が問合せの条件句を満たしていない場合でも(DEPARTMENT_ID = 5の場合など)、データベースからアプリケーションにOCNが送信されます。

例11-1 変更通知として登録される問合せ

SELECT EMPLOYEE_ID, SALARY
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 10;

問合せ結果変更通知(QRCN)


注意:

QRCNを使用するには、データベースのCOMPATIBLE初期化パラメータが11.0.0以上であり、自動UNDO管理(AUM)が有効(デフォルト設定)である必要があります。

COMPATIBLE初期化パラメータの詳細は、『Oracle Database管理者ガイド』を参照してください。

AUMの詳細は、『Oracle Database管理者ガイド』を参照してください。


アプリケーションで問合せ結果変更通知(QRCN)に対する問合せが登録されると、その問合せの結果がトランザクションによって変更されてコミットされるたびに、データベースからアプリケーションにQRCNが送信されます。

たとえば、アプリケーションで例11-1のQRCNに対する問合せが登録されると、問合せ結果セットが変更された場合のみ、つまり、次のデータ操作言語(DML)文のいずれかがコミットされた場合にのみ、データベースからアプリケーションにQRCNが送信されます。

  • 問合せの条件句(DEPARTMENT_ID = 10)を満たす行のINSERTまたはDELETE

  • 問合せの条件句(DEPARTMENT_ID = 10)を満たしている行のEMPLOYEE_IDまたはSALARY列へのUPDATE

  • 行の値が10から10以外の値に変更され、その行が結果セットから削除される原因となったDEPARTMENT_ID列へのUPDATE

  • 行の値が10以外の値から10に変更され、その行が結果セットに追加される原因となったDEPARTMENT_ID列へのUPDATE

デフォルトの通知タイプはOCNです。QRCNの場合は、CQ_NOTIFICATION$_REG_INFOオブジェクトのQOSFLAGS属性にQOS_QUERYを指定します。

QRCNでは、保証モード(デフォルト)またはベストエフォート・モードを選択できます。

内容は次のとおりです。

保証モード

保証モードでは、誤検出はありません。つまり、問合せ結果セットの変更が保証される場合にのみ、データベースからアプリケーションにQRCNが送信されます。

たとえば、アプリケーションで例11-1のQRCNに対する問合せが登録され、従業員201が部門10に所属しており、次の文が実行されるとします。

UPDATE EMPLOYEES
SET SALARY = SALARY + 10
WHERE EMPLOYEE_ID = 201;

UPDATE EMPLOYEES
SET SALARY = SALARY - 10
WHERE EMPLOYEE_ID = 201;

COMMIT;

このトランザクションの各UPDATE文によって問合せ結果セットは変更されますが、各文を合計すると問合せ結果セットへの影響はないため、このトランザクションに対してはデータベースからアプリケーションにQRCNは送信されません。

保証モードでは、CQ_NOTIFICATION$_REG_INFOオブジェクトのQOSFLAGS属性にQOS_BEST_EFFORTではなくQOS_QUERYを指定します。

問合せの中には、保証モードのQRCNに対して複雑すぎるものがあります。保証モードで登録可能な問合せの特性は、「保証モードでQRCNに対して登録可能な問合せ」を参照してください。

ベストエフォート・モード

保証モードでは複雑すぎる問合せの中には、ベストエフォート・モードでQRCNに対して登録できるものがあります。このモードでは、簡略バージョンの問合せがCQNによって作成および登録されます。

たとえば、例11-2の問合せは、集計関数SUMを含んでおり、保証モードのQRCNに対しては複雑すぎます。

例11-2 保証モードのQRCNに対して複雑すぎる問合せ

SELECT SUM(SALARY)
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 20;

ベストエフォート・モードでは、例11-2の問合せの次のような簡略バージョンがCQNによって登録されます。

SELECT SALARY
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 20;

元の問合せの結果が変更されるたびに、その簡略バージョンの結果も変更されるため、簡略化が原因で通知が失われることはありません。ただし、簡略バージョンの結果は元の問合せの結果が変更されなくても変更される場合があるため、簡略化によって誤検出が発生することがあります。

ベストエフォート・モードでは、データベースは次の処理を行います。

  • 通知関連の処理によるOLTPレスポンスのオーバーヘッドを次のように最小化します。

    • 単一表問合せの場合、データベースでは、どの列が変更されたか、および変更された行によってどの条件句が満たされたかに基づいて、問合せ結果が変更されたかどうかを判断します。

    • 複数表問合せ(結合)の場合、データベースでは、複数の表の間の主キー/外部キー制約関係を使用して、問合せ結果が変更されたかどうかを判断します。

  • DML文によって問合せ結果セットが変更されるたびに、最初のDML文によって行われた変更が後続のDML文によって無効になった場合でも、アプリケーションにQRCNを送信します。

ベストエフォート・モードでのオーバーヘッドを最小化により、CQNで簡略化されない問合せに対しても、誤検出がまれに発生します。たとえば、例11-1の問合せと、「保証モード」のトランザクションを想定します。ベストエフォート・モードでは、CQNによって問合せは簡略化されませんが、トランザクションによって誤検出が発生します。

一部のタイプの問合せは非常に簡略化されているため、無効化がオブジェクト・レベルで発生します。つまり、該当の問合せで参照されるいずれかのオブジェクトが変更されるたびに発生します。このような問合せの例としては、サポートされていない列型を使用する問合せや、副問合せを含んでいる問合せがあります。この問題を解決するには、元の問合せを書き換えます。

たとえば、例11-3の問合せは、副問合せを含んでいるため、保証モードのQRCNに対しては複雑すぎます。

例11-3 簡略バージョンによってオブジェクトが無効になる問合せ

SELECT SALARY
FROM EMPLOYEES
WHERE DEPARTMENT_ID IN (
  SELECT DEPARTMENT_ID
  FROM DEPARTMENTS
  WHERE LOCATION_ID = 1700
);

ベストエフォート・モードでは、例11-3の問合せがCQNによって次のように簡略化されます。

SELECT * FROM EMPLOYEES, DEPARTMENTS;

問合せの簡略化により、オブジェクトが無効になる場合があります。ただし、元の問合せを次のように書き換えると、その問合せを保証モードまたはベストエフォート・モードで登録できます。

SELECT SALARY
FROM EMPLOYEES, DEPARTMENTS
WHERE EMPLOYEES.DEPARTMENT_ID = DEPARTMENTS.DEPARTMENT_ID
  AND DEPARTMENTS.LOCATION_ID = 1700;

ベストエフォート・モードでのみ登録可能な問合せについては、「ベストエフォート・モードでのみQRCNに対して登録可能な問合せ」で説明します。

デフォルトのQRCNモードは保証モードです。ベストエフォート・モードの場合は、CQ_NOTIFICATION$_REG_INFOオブジェクトのQOSFLAGS属性にQOS_BEST_EFFORTを指定します。

通知を生成するイベント

通知を生成するイベントは次のとおりです。

DMLトランザクションのコミット

通知タイプがOCNの場合、1つ以上の登録済オブジェクトを変更するあらゆるDMLトランザクションで、コミット時に各オブジェクトに対して通知が1つ生成されます。

通知タイプがQRCNの場合、1つ以上の登録済問合せの結果を変更するあらゆるDMLトランザクションで、コミット時に通知が生成されます。この通知には、結果が変更された問合せのIDが含まれます。

どちらの通知タイプでも、通知には次の内容が含まれます。

  • 変更された各表の名前

  • 操作タイプ(INSERTUPDATEまたはDELETE)

  • 変更された各行のROWID(ROWIDオプションを使用して登録が作成され、変更された行の数があまり多くない場合)。詳細は、「ROWIDオプション」を参照。

DDL文のコミット

OCNとQRCNの両方について、次のデータ定義言語(DDL)文により、コミット時に通知が生成されます。

  • ALTER TABLE

  • TRUNCATE TABLE

  • FLASHBACK TABLE

  • DROP TABLE


注意:

通知タイプがOCNの場合、DROP TABLE文のコミットによってDROP NOTIFICATIONが生成されます。

削除された表に対する問合せのOCN登録は、その表(すでに存在しない表)から関連付けが解除されますが、登録自体は存続します。これらの登録のいずれかが削除された表以外のオブジェクトに関連付けられている場合、それらのオブジェクトに対する変更がコミットされると、通知は引き続き生成されます。削除された表にのみ関連付けられていた登録も存続し、その作成者は問合せ(およびその参照オブジェクト)をその登録に追加できます。

OCN登録は、問合せの登録時点におけるオブジェクトのバージョンと定義に基づきます。オブジェクトが削除されると、そのオブジェクトの登録の関連付けはオブジェクトから永続的に解除されます。オブジェクトが削除されたオブジェクトと同じ名前および同じスキーマで作成された場合、作成されたオブジェクトは削除されたオブジェクトに関連付けられていたOCN登録には関連付けられません。


通知タイプがQRCNの場合、次のようになります。

  • 通知には次の内容が含まれます。

    • 結果が変更された問合せのID

    • 変更された表の名前

    • DDL操作のタイプ

  • 登録済問合せを無効にするDDL操作の中には、その問合せを登録解除する原因となるものもあります。

    たとえば、次の問合せがQRCNに対して登録されるとします。

    SELECT COL1 FROM TEST_TABLE
      WHERE COL2 = 1;
    

    TEST_TABLEのスキーマは次のとおりとします。

    (COL1 NUMBER, COL2 NUMBER, COL3 NUMBER)
    

    この場合、次のDDL文により、コミット時に問合せが無効になり、問合せが登録から削除されます。

    ALTER TABLE DROP COLUMN COL2;
    

登録解除

OCNとQRCNの両方について、登録解除(データベースからの登録の削除)によって通知が生成されます。データベースで登録が削除される原因は次のとおりです。

  • タイムアウト

    問合せの登録時にTIMEOUTがゼロ以外の値で指定された場合、指定の時間間隔後にデータベースによって登録がパージされます。

    問合せの登録時にQOS_DEREG_NFYが指定された場合、最初の通知の生成後にデータベースによって登録がパージされます。

  • 権限の消失

    登録済問合せに関連付けられているオブジェクトに対する権限が消失し、通知タイプがOCNの場合、データベースによって登録がパージされます。(通知タイプがQRCNの場合は、データベースによってその問合せは登録から削除されますが、登録はパージされません。)

    問合せの登録に必要な権限は、「CQN登録を作成するための前提条件」を参照してください。

クライアント・アプリケーションによる明示的な登録解除の実行時には、通知は生成されません。

グローバル・イベント

グローバル・イベントEVENT_STARTUPおよびEVENT_SHUTDOWNにより、通知が生成されます。

Oracle RAC環境では、次のイベントによって通知が生成されます。

  • EVENT_STARTUP(データベースの最初のインスタンスの起動時)

  • EVENT_SHUTDOWN(データベースの最終インスタンスの停止時)

  • EVENT_SHUTDOWN_ANY(データベースのいずれかのインスタンスの停止時)

前述のグローバル・イベントは、DBMS_CQ_NOTIFICATIONパッケージで定義されている定数です。


参照:

DBMS_CQ_NOTIFICATIONパッケージの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

通知内容

通知には、次の情報の一部またはすべてが含まれます。

  • イベントのタイプ(次のいずれか)

    • 起動

    • オブジェクト変更

    • 問合せ結果変更

    • 登録解除

    • 停止

  • 影響を受けた登録の登録ID

  • 変更されたオブジェクトの名前

  • ROWIDオプションが指定されている場合の、変更された行のROWID

  • 通知タイプがQRCNの場合の、結果が変更された問合せの問合せID

  • 通知がDMLまたはDDL文の結果として生成された場合

    • 変更された表の名前の配列

    • 操作タイプ(INSERTUPDATEなど)

通知には、変更されたデータ自体は含まれません。たとえば、5000から6000への月給の増額があっても、通知には示されません。変更されたオブジェクト、行または問合せ結果の最新の値を取得するには、アプリケーションからデータベースに問い合せる必要があります。

CQNに適したアプリケーション

CQNに適したアプリケーションは、データベースへのネットワーク・ラウンドトリップを回避するために、変更の頻度の低いオブジェクトに対する問合せの結果セットを中間層にキャッシュするアプリケーションです。これらのアプリケーションでは、CQNを使用して、キャッシュされる問合せを登録できます。このようなアプリケーションは、通知を受信すると、登録済問合せを再実行してキャッシュをリフレッシュできます。

このようなアプリケーションの例としては、Webフォーラムがあります。Webフォーラムのユーザーは、コンテンツがデータベースに挿入されても、挿入後すぐにそのコンテンツを参照する必要はないため、このアプリケーションでは情報を中間層にキャッシュし、キャッシュをいつリフレッシュするかをCQNで指示できます。

図11-1に、データがデータベースから提供され、中間にキャッシュされた後、インターネット経由でアクセスされる一般的な使用例を示します。

図11-1 中間層キャッシュ

図11-1の説明が続きます。
「図11-1 中間層キャッシュ」の説明

中間層のアプリケーションは、キャッシュをデータベースと相対でできるかぎり最新の状態に保ちつつ、データベース・オブジェクトのキャッシュ・コピーに迅速にアクセスする必要があります。キャッシュ・データは、トランザクションでデータが変更されてコミットされると不要になるため、アプリケーションが不正な結果にアクセスする危険性があります。アプリケーションがCQNを使用している場合、データベースは、登録済オブジェクトに変更が発生した時点で変更内容の詳細を使用して通知を公開できます。この通知に応答して、アプリケーションではキャッシュ・データをバックエンド・データベースからフェッチしてリフレッシュできます。

図11-2に、中間層のWebクライアントが通知を受信して処理するプロセスを示します。

図11-2 連続問合せ通知(CQN)の基本プロセス

図11-2の説明は図の下のリンクをクリックしてください。
「図11-2 連続問合せ通知(CQN)の基本プロセス」の説明

図11-2の各手順は次のとおりです(PL/SQLを使用して登録が作成され、アプリケーションによりHR.EMPLOYEESに対する問合せの結果セットがキャッシュされている場合)。

  1. 開発者は、PL/SQLを使用して、問合せに対するCQN登録を作成します。このプロセスでは、通知を処理するストアドPL/SQLプロシージャを作成した後、PL/SQL CQNインタフェースを使用して問合せに対する登録を作成し、作成したPL/SQLプロシージャを通知ハンドラとして指定します。

  2. データベースでは、データ辞書に登録情報が移入されます。

  3. ユーザーがバックエンド・データベースのHR.EMPLOYEES表の行を更新し、その更新をコミットすると、問合せ結果が変更されます。これで、中間層でキャッシュされていたHR.EMPLOYEESのデータが無効になります。

  4. データベースにより、内部キューに変更を説明するメッセージが追加されます。

  5. データベースからJOBQバックグラウンド・プロセスに、通知メッセージが通知されます。

  6. JOBQプロセスにより、クライアント・アプリケーションから指定されたストアド・プロシージャが実行されます。この例では、JOBQからサーバー側PL/SQLプロシージャにデータが渡されます。PL/SQL通知ハンドラの実装により、通知の処理方法が決まります。

  7. 開発者は、サーバー側PL/SQLプロシージャ内に、登録済オブジェクトに対する変更を中間層のクライアント・アプリケーションに通知するための論理を実装できます。たとえば、HR.EMPLOYEES内で変更された行のROWIDをアプリケーションに通知します。

  8. 中間層のクライアント・アプリケーションでは、バックエンド・データベースを問い合せて、変更があった行のデータを取得します。

  9. クライアント・アプリケーションにより、キャッシュがこのデータで更新されます。

CQN登録の作成

CQN登録により、1つ以上の問合せのリストが通知タイプおよび通知ハンドラに関連付けられます。

通知タイプは、OCNまたはQRCNです。これらのタイプの詳細は、「オブジェクト変更通知(OCN)」および「問合せ結果変更通知(QRCN)」を参照してください。

CQN登録を作成するには、PL/SQLインタフェースまたはOCIを使用できます。PL/SQLインタフェースを使用する場合、通知ハンドラはサーバー側のPL/SQLストアド・プロシージャになり、OCIを使用する場合、通知ハンドラはクライアント側のCコールバック・プロシージャになります。(このトピックでは、PL/SQLインタフェースのみについて説明します。OCIの詳細は『Oracle Call Interfaceプログラマーズ・ガイド』を参照してください)。

作成された登録は、データベースに格納されます。Oracle RAC環境では、この登録はすべてのデータベース・インタフェースから参照できます。いずれかのデータベース・インスタンスの問合せ結果がトランザクションによって変更されると、通知が生成されます。

デフォルトでは、登録は、それを作成したアプリケーションによって明示的に登録解除されるまで、または(権限の消失などが原因で)データベースによって暗黙的にパージされるまで存続します。

内容は次のとおりです。

PL/SQL CQN登録インタフェース

PL/SQL CQN登録インタフェースは、DBMS_CQ_NOTIFICATIONパッケージを使用して実装されます。登録ブロックを開くには、DBMS_CQ_NOTIFICATION.NEW_REG_STARTファンクションを使用します。通知タイプや通知ハンドラなどの登録詳細は、CQ_NOTIFICATION$_REG_INFOオブジェクトの一部として指定し、このオブジェクトは引数としてNEW_REG_STARTプロシージャに渡されます。登録ブロックがオープンの間に実行したすべての問合せは、CQNに登録されます。通知タイプとしてQRCNを指定すると、データベースによって各問合せに問合せIDが割り当てられます。この問合せIDは、DBMS_CQ_NOTIFICATION.CQ_NOTIFICATION_QUERYIDファンクションを使用して取得できます。登録ブロックをクローズするには、DBMS_CQ_NOTIFICATION.REG_ENDファンクションを使用します。

この手順の詳細は、「PL/SQLを介したCQNに対する問合せの登録」を参照してください。


参照:

DBMS_CQ_NOTIFICATIONパッケージの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

CQN登録オプション

CQN登録のデフォルトは、表11-1に示すオプションを使用して変更できます。

表11-1 連続問合せ通知登録オプション

オプション 説明

通知タイプ

QRCNを指定します(デフォルトはOCN)。

QRCNモード脚注1

ベストエフォート・モードを指定します(デフォルトは保証モード)。

ROWID

変更された各行のROWID疑似列の値を通知に含めます。

操作フィルタ脚注2

指定したフィルタ条件を操作タイプが満たした場合のみ、通知を公開します。

トランザクション・ラグ脚注2

非推奨。かわりに通知グループ化を使用してください。

通知グループ化

通知のグループ化方法を指定します。

信頼可能

通知を(デフォルトの共有メモリーではなく)永続データベース・キューに格納します。

通知時にパージ

最初の通知後に登録をパージします。

タイムアウト

指定の時間間隔後に登録をパージします。


脚注1 通知タイプがQRCNの場合にのみ適用されます。

脚注2 通知タイプがOCNの場合にのみ適用されます。

内容は次のとおりです。

「通知タイプ」オプション

通知タイプは、OCN(「オブジェクト変更通知(OCN)」を参照)およびQRCN(「問合せ結果変更通知(QRCN)」を参照)です。

QRCNモード(QRCN通知タイプのみ)

QRCNモード・オプションは、通知タイプがQRCNの場合にのみ適用されます。通知タイプをQRCNに設定する手順は、「「通知タイプ」オプション」を参照してください。

QRCNモードには、保証モード(「保証モード」を参照)とベストエフォート・モード(「ベストエフォート・モード」を参照)があります。

デフォルトは保証モードです。ベストエフォート・モードの場合は、CQ_NOTIFICATION$_REG_INFOオブジェクトのQOSFLAGS属性にQOS_BEST_EFFORTを指定します。

ROWIDオプション

ROWIDオプションにより、変更された行それぞれのROWID疑似列の値(その行のrowid)が通知に含まれるようになります。変更された各行のROWIDオプションを通知に含めるには、CQ_NOTIFICATION$_REG_INFOオブジェクトのQOSFLAGS属性にQOS_ROWIDSを指定します。


注意:

ハイブリッド列圧縮(HCC)で圧縮された表の行を更新すると、行のROWIDが変更されます。特定のOracleストレージ・システムの機能であるHCCの詳細は、『Oracle Database概要』を参照してください。

アプリケーションでは、次の形式の問合せを実行すると、変更された行の内容を通知のROWID情報から取得できます。

SELECT * FROM table_name_from_notification
WHERE ROWID = rowid_from_notification;

ROWIDは、外部文字列形式で公開されます。通常のヒープ表では、ROWIDの長さは18バイトです。索引構成表(IOT)では、ROWIDの長さは主キーのサイズによって異なり、18バイトより長い場合があります。

ROWIDに十分なメモリーがサーバーにない場合、通知はFULL-TABLE-NOTIFICATIONにロールアップされることがあります(これは、通知記述子内の特殊フラグで示されます)。FULL-TABLE-NOTIFICATIONに対して考えられる原因は次のとおりです。

  • ROWIDによって消費される共有メモリーの合計が動的共有プール・サイズの1%を超えています。

  • 1回のトランザクションで1つの登録済オブジェクト内で変更された行が多すぎます(上限は約80行)。

  • IOTについて変更された行の論理ROWIDの合計長が長すぎます(上限は約1800バイト)。

  • 通知グループ化オプションNTFN_GROUPING_TYPEに値DBMS_CQ_NOTIFICATION.NTFN_GROUPING_TYPE_SUMMARYが指定されています(「通知グループ化オプション」を参照)。

FULL-TABLE-NOTIFICATIONにはROWIDは含まれないため、これを受信したアプリケーションでは表全体(つまり、すべての行)が変更された可能性があるとみなされます。

操作フィルタ・オプション(OCN通知タイプのみ)

操作フィルタ・オプションは、通知タイプがOCNの場合にのみ適用されます。

操作フィルタ・オプションを使用すると、通知を生成する操作のタイプを指定できます。

デフォルトは全操作です。一部の操作でのみ通知が生成されるように指定するには、CQ_NOTIFICATION$_REG_INFOオブジェクトのOPERATIONS_FILTER属性を使用します。OPERATIONS_FILTER属性では、操作のタイプを表す定数を使用してタイプを指定し、この定数は、DBMS_CQ_NOTIFICATIONパッケージで次のように定義されています。

操作 定数
INSERT DBMS_CQ_NOTIFICATION.INSERTOP
UPDATE DBMS_CQ_NOTIFICATION.UPDATEOP
DELETE DBMS_CQ_NOTIFICATION.DELETEOP
ALTEROP DBMS_CQ_NOTIFICATION.ALTEROP
DROPOP DBMS_CQ_NOTIFICATION.DROPOP
UNKNOWNOP DBMS_CQ_NOTIFICATION.UNKNOWNOP
すべて(デフォルト) DBMS_CQ_NOTIFICATION.ALL_OPERATIONS

複数の操作を指定するには、ビット単位のORを使用します。次に例を示します。

DBMS_CQ_NOTIFICATION.INSERTOP + DBMS_CQ_NOTIFICATION.DELETEOP

QOS_QUERYは通知タイプとしてQRCNを指定するため、QOSFLAGS属性にQOS_QUERYも指定した場合はOPERATIONS_FILTERは無効です。


参照:

DBMS_CQ_NOTIFICATIONパッケージの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

トランザクション・ラグ・オプション(OCN通知タイプのみ)

トランザクション・ラグ・オプションは、通知タイプがOCNの場合にのみ適用されます。


注意:

このオプションは非推奨です。フロー制御の通知を実装するには、「通知グループ化オプション」を使用してください。

トランザクション・ラグ・オプションでは、クライアント・アプリケーションがデータベースから遅れることのできるトランザクション数を指定します。数が0の場合、登録済オブジェクトを変更するトランザクションごとに通知が送信されます。数が5の場合、登録済オブジェクトを変更するトランザクションのうち5番目ごとに通知が送信されます。データベースでは、クライアントで中間の変更が失われないように、中間の変更をオブジェクトの粒度で追跡して通知に含めます。

0より大きいトランザクション・ラグが役立つのは、アプリケーションでフロー制御の通知を実装している場合のみです。アプリケーションでは、通知がラグに達する程度に十分な頻度で生成されるようにし、無限に遅延されないようにしてください。

TRANSACTION_LAGを指定すると、QOS_ROWIDSも指定した場合でも、通知にROWIDは含まれません。

通知グループ化オプション

デフォルトでは、通知はその原因となるイベントの直後に生成されます。

通知グループ化オプションは、CQ_NOTIFICATION$_REG_INFOオブジェクトの属性であり、次の種類があります。

属性 説明
NTFN_GROUPING_CLASS 通知をグループ化するクラスを指定します。使用可能な値は、DBMS_CQ_NOTIFICATION.NTFN_GROUPING_CLASS_TIME(通知を時間でグループ化)と、デフォルトのゼロ(通知をその原因となるイベントの直後に生成)のみです。
NTFN_GROUPING_VALUE グループを定義する時間間隔を秒単位で指定します。たとえば、この値が900の場合、同じ15分間隔内に生成された通知がグループ化されます。
NTFN_GROUPING_TYPE 次のいずれかのグループ化のタイプを指定します。
  • DBMS_CQ_NOTIFICATION.NTFN_GROUPING_TYPE_SUMMARY: グループ内のすべての通知は、単一の通知に要約されます。

    注意: ROWIDオプションを指定した場合でも、この単一の通知にはROWIDは含まれません。

  • DBMS_CQ_NOTIFICATION.NTFN_GROUPING_TYPE_LAST: グループ内の最後の通知のみが公開され、それより前の通知は破棄されます。

NTFN_GROUPING_START_TIME 通知生成の開始時間を指定します。NULLが指定されると、システム生成の現在の時間がデフォルトになります。
NTFN_GROUPING_REPEAT_COUNT 通知を繰り返す回数を指定します。登録の存続中に通知を永続的に受信するには、DBMS_CQ_NOTIFICATION.NTFN_GROUPING_FOREVERに設定します。登録の存続中に最大でnの通知を受信するには、nに設定します。


注意:

タイムアウト、権限の消失およびグローバル・イベントによって生成された通知は、指定したグループ化間隔が終了する前に公開される場合があります。この場合、グループ化された保留中の通知が存在すると、間隔が終了する前にその通知も公開されます。

信頼可能オプション

デフォルトでは、CQN登録は共有メモリーに格納されます。これをかわりに永続データベース・キューに格納するには(つまり、信頼できる通知を生成するには)、CQ_NOTIFICATION$_REG_INFOオブジェクトのQOSFLAGS属性にQOS_RELIABLEを指定します。

信頼できる通知のメリットは、その生成後にデータベースで障害が発生しても、再起動後にその通知を配信できることです。Oracle RAC環境では、正常なデータベース・インスタンスがこの通知を配信できます。

信頼できる通知のデメリットは、デフォルトの通知よりもCPUおよびI/Oのコストが高いことです。

「通知時にパージ」および「タイムアウト」オプション

デフォルトでは、CQN登録は、それを作成したアプリケーションによって明示的に登録解除されるまで、または(権限の消失などが原因で)データベースによって暗黙的にパージされるまで存続します。

登録の最初の通知の生成後にその登録をパージするには、CQ_NOTIFICATION$_REG_INFOオブジェクトのQOSFLAGS属性にQOS_DEREG_NFYを指定します。

n秒後に登録をパージするには、CQ_NOTIFICATION$_REG_INFOオブジェクトのTIMEOUT属性にnを指定します。

「通知時にパージ」と「タイムアウト」の2つのオプションは、同時に使用できます。

CQN登録を作成するための前提条件

CQN登録を作成するための前提条件は次のとおりです。

  • 次の権限が必要です。

    • DBMS_CQ_NOTIFICATIONパッケージのEXECUTE権限(登録の作成にこのパッケージのサブプログラムを使用)

    • CHANGE NOTIFICATIONシステム権限

    • 登録するすべてのオブジェクトに対するSELECT権限

    登録済の問合せに関連付けられているオブジェクトに対する権限を失うと、通知が生成されます(「登録解除」を参照)。

  • SYS以外のユーザーとして接続する必要があります。

  • コミットされていないトランザクションの途中でない必要があります。

  • dml_locks init.oraパラメータの値がゼロ以外である必要があります(デフォルト値はゼロ以外です)。

    (これは、通知を受信するための前提条件でもあります。)


注意:

QRCNを使用するには、データベースのCOMPATIBLE設定が11.0.0以上である必要があります。

オブジェクト変更通知(OCN)に対して登録可能な問合せ

ストアド・プロシージャやREFカーソルの一部として実行される問合せなど、ほとんどの問合せをOCNに対して登録できます。

OCNに対して登録不可能な問合せは次のとおりです。

  • 固定表または固定ビューに対する問合せ

  • ユーザー・ビューに対する問合せ

  • データベース・リンク(dblink)を含む問合せ

  • マテリアライズド・ビューでの問合せ


注意:

OCN登録ではシノニムを使用できますが、QRCN登録では使用できません。

問合せ結果変更通知(QRCN)に対して登録可能な問合せ

QRCNに対して保証モードで登録可能な問合せ、QRCNに対してベストエフォート・モードでのみ登録可能な問合せ、およびQRCNに対してどちらのモードでも登録不可能な問合せがあります。(モードの詳細は、「保証モード」および「ベストエフォート・モード」を参照してください。)

内容は次のとおりです。

保証モードでQRCNに対して登録可能な問合せ

問合せを保証モードでQRCNに対して登録するには、問合せを次のルールに準拠させる必要があります。

  • 参照するすべての列がNUMBERまたはVARCHAR2データ型である必要があります。

  • 列の式に含まれる算術演算子が次のバイナリ演算子に制限され、そのオペランドが数値データ型の列である必要があります。

    • +(加算)

    • -(減算、単項マイナスではない)

    • *(乗算)

    • /(除算)

  • 条件句の比較演算子は次の演算子に制限されます。

    • <(より小さい)

    • <=(以下)

    • =(等しい)

    • >=(以上)

    • >(より大きい)

    • <>または!=(等しくない)

    • IS NULL

    • IS NOT NULL

  • 条件句のBoolean演算子はANDORおよびNOTに制限されます。

  • 問合せに集計関数(SUMCOUNTAVERAGEMINMAXなど)は含められません。

    SQL集計関数のリストについては、『Oracle Database SQL言語リファレンス』を参照してください。

保証モードでは、単一表および一部の内部等価結合に対するほとんどの問合せが可能です(次の例を参照)。

SELECT SALARY FROM EMPLOYEES, DEPARTMENTS
  WHERE EMPLOYEES.DEPARTMENT_ID = DEPARTMENTS.DEPARTMENT_ID
    AND DEPARTMENTS.LOCATION_ID = 1700;

注意:

  • 問合せオプティマイザで使用される実行計画により、問合せが保証モードでは矛盾する場合があります(OR拡張など)。問合せオプティマイザの詳細は、『Oracle Databaseパフォーマンス・チューニング・ガイド』を参照してください。

  • 保証モードで登録可能な問合せは、ベストエフォート・モードでも登録可能ですが、ベストエフォート・モードではCQNで簡略化されない問合せに対しても誤検出が発生する可能性があるため、結果は異なる場合があります。詳細は、「ベストエフォート・モード」を参照してください。


ベストエフォート・モードでのみQRCNに対して登録可能な問合せ

次のいずれかの条件を満たす問合せは、ベストエフォート・モードでのみQRCNに対して登録可能であり、その簡略バージョンでは通知がオブジェクトの粒度で生成されます。

  • 暗号化が有効にされている列を参照する問合せ

  • 同じ型の項目がSELECT構文のリストに11以上ある問合せ

  • 次のいずれかを使用した式を含む問合せ

    • 文字列関数(SUBSTRLTRIMRTRIMなど)

    • 算術関数(TRUNCABSSQRTなど)

      SQL関数のリストについては、『Oracle Database SQL言語リファレンス』を参照してください。

    • パターン一致条件LIKEおよびREGEXP_LIKE

    • EXISTSまたはNOT EXISTS条件

  • 別の表の列で定義されている条件句を使用した論理和を含む問合せ。次に例を示します。

    SELECT EMPLOYEE_ID, DEPARTMENT_ID
      FROM EMPLOYEES, DEPARTMENTS
        WHERE EMPLOYEES.EMPLOYEE_ID = 10
          OR DEPARTMENTS.DEPARTMENT_ID = 'IT';
    
  • ユーザーROWIDアクセスを含む問合せ。次に例を示します。

    SELECT DEPARTMENT_ID
      FROM DEPARTMENTS
        WHERE ROWID = 'AAANkdAABAAALinAAF';
    
  • 内部結合以外の結合を含む問合せ

  • 次のいずれかを使用した実行計画を含む問合せ

    • ビットマップ結合索引、ドメイン索引またはファンクション索引

    • UNION ALLまたはCONCATENATION

      (問合せ自体の内部、または問合せオプティマイザで選択されたOR拡張実行計画の結果内で使用。)

    • ORDER BYまたはGROUP BY

      (問合せ自体の内部、または問合せオプティマイザで選択された実行計画内のORDER BYオプションを使用したSORT操作の結果内で使用。)

    • オーバーフロー・セグメントがあり、パーティション化された索引構成表(IOT)

    • クラスタ・オブジェクト

    • パラレル実行

どちらのモードでもQRCNに対して登録不可能な問合せ

次のいずれかを参照する問合せは、保証モードとベストエフォート・モードのどちらでもQRCNに対して登録不可能です。

  • ビュー

  • 固定表、リモート表または仮想プライベート・データベース(VPD)ポリシーが有効化されている表

  • DUAL(SELECT構文のリスト内)

  • シノニム

  • ユーザー定義のPL/SQLサブプログラムのコール

  • 「保証モードでQRCNに対して登録可能な問合せ」にリストされていない演算子

  • 集計関数COUNT

    (他の集計関数は、ベストエフォート・モードでは登録可能ですが、保証モードでは登録不可能です。)

  • アプリケーション・コンテキスト(次の例を参照)

    SELECT SALARY FROM EMPLOYEES
    WHERE USER = SYS_CONTEXT('USERENV', 'SESSION_USER');
    
  • SYSDATESYSTIMESTAMPまたはCURRENT TIMESTAMP

また、マテリアライズド・ビューを使用して問合せオプティマイザがリライトした問合せはQRCNに対して登録できません。問合せオプティマイザの詳細は、『Oracle Databaseパフォーマンス・チューニング・ガイド』を参照してください。

PL/SQLを介したCQNに対する問合せの登録

PL/SQLを使用してCQN登録を作成する手順は、次のとおりです。

  1. 通知ハンドラとして機能するストアドPL/SQLプロシージャを作成します。

  2. 通知ハンドラの名前、通知タイプ、および登録のその他の属性を指定するCQ_NOTIFICATION$_REG_INFOオブジェクトを作成します。

  3. クライアント・アプリケーションで、DBMS_CQ_NOTIFICATION.NEW_REG_STARTファンクションを使用して登録ブロックをオープンします。

  4. 登録する問合せを実行します(DML操作またはDDL操作は実行しないでください)。

  5. DBMS_CQ_NOTIFICATION.REG_ENDファンクションを使用して登録ブロックをクローズします。

内容は次のとおりです。


参照:

CQ_NOTIFICATION$_REG_INFOオブジェクトとファンクションNEW_REG_STARTおよびREG_ENDの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。それらすべてはDBMS_CQ_NOTIFICATIONパッケージで定義されています。

PL/SQL通知ハンドラの作成

通知ハンドラとして使用するPL/SQLストアド・プロシージャの作成時には、次のシグネチャを含める必要があります。

PROCEDURE schema_name.proc_name(ntfnds IN CQ_NOTIFICATION$_DESCRIPTOR)

このシグネチャで、schema_nameはデータベース・スキーマ名、proc_nameはストアド・プロシージャ名、ntfndsは通知記述子を示します。

通知記述子はCQ_NOTIFICATION$_DESCRIPTORオブジェクトであり、その属性によって変更の詳細(トランザクションID、変更のタイプ、影響を受けた問合せ、変更された表など)が記述されます。

通知記述子ntfndsJOBQプロセスから通知ハンドラproc_nameに渡され、このハンドラがアプリケーション要件に従って通知を処理します。(これは図11-2の手順6に示します。)


注意:

通知ハンドラは、ジョブ・キュー・プロセス内で実行されます。JOB_QUEUE_PROCESSES初期化パラメータでは、ジョブの実行用に作成できるプロセスの最大数を指定します。PL/SQL通知を受信するには、JOB_QUEUE_PROCESSESをゼロ以外の値に設定する必要があります。

CQ_NOTIFICATION$_REG_INFOオブジェクトの作成

タイプCQ_NOTIFICATION$_REG_INFOのオブジェクトでは、登録済オブジェクトの変更時にデータベースで実行される通知ハンドラを指定します。SQL*Plusでは、次の文を実行してそのタイプ属性を表示できます。

DESC CQ_NOTIFICATION$_REG_INFO

表11-2に、SYS.CQ_NOTIFICATION$_REG_INFOの属性を示します。

表11-2 CQ_NOTIFICATION$_REG_INFOの属性

属性 説明

CALLBACK

通知の生成時に実行されるPL/SQLプロシージャ(通知ハンドラ)の名前を指定します。この名前は、hr.dcn_callbackのようにschema_name.procedure_name形式で指定する必要があります。

QOSFLAGS

1つ以上のサービスのクオリティ・フラグ(DBMS_CQ_NOTIFICATIONパッケージ内の定数)を指定します。この名前と説明は、表11-3を参照してください。

複数のサービスのクオリティ・フラグを指定するには、ビット単位のORを使用します。たとえば、DBMS_CQ_NOTIFICATION.QOS_RELIABLE + DBMS_CQ_NOTIFICATION.QOS_ROWIDSなどです。

TIMEOUT

登録のタイムアウト期間を指定します。0(ゼロ)以外の値に設定する場合は、データベースにより登録がパージされるまでの秒数を指定します。0またはNULLの場合、登録はクライアントにより明示的に解除されるまで存続します。

QOSFLAGS属性およびそのQOS_DEREG_NFYフラグと併用できます。

OPERATIONS_FILTER

OCN(「オブジェクト変更通知(OCN)」を参照)にのみ適用されます。QOS_FLAGS属性にQOS_QUERYフラグが指定されている場合は無効です。

SQL文の型に基づいてメッセージをフィルタリングします。DBMS_CQ_NOTIFICATIONパッケージ内の次の定数を指定できます。

  • ALL_OPERATIONS。すべての変更時に通知します。

  • INSERTOP。INSERT時に通知します。

  • UPDATEOP。UPDATE時に通知します。

  • DELETEOP。DELETE時に通知します。

  • ALTEROPALTER TABLE操作時に通知します。

  • DROPOPDROP TABLE操作時に通知します。

  • UNKNOWNOP。不明な操作時に通知します。

ビット単位のORを使用すると、操作の組合せを指定できます。たとえば、DBMS_CQ_NOTIFICATION.INSERTOP + DBMS_CQ_NOTIFICATION.DELETEOPなどです。

TRANSACTION_LAG

非推奨。フロー制御の通知を実装するには、NTFN_GROUPING_*属性を使用してください。

OCN(「オブジェクト変更通知(OCN)」を参照)にのみ適用されます。QOS_FLAGS属性にQOS_QUERYフラグが指定されている場合は無効です。

クライアントがデータベースから遅れることのできるトランザクション数またはデータベース変更数を指定します。0の場合、クライアントは無効化メッセージを生成直後に受信します。5の場合、登録済オブジェクトを変更するトランザクションのうち5番目ごとに通知が送信されます。データベースでは、中間の変更がオブジェクトの粒度で追跡され、変更が通知とともにバンドルされます。そのため、クライアントから中間の変更が失われることはありません。

トランザクションのコミット時にオブジェクトの変更通知をそれ以上の遅延なしで受信する必要のあるほとんどのアプリケーションでは、トランザクション・ラグ0(ゼロ)を選択するように期待されます。ゼロ以外のトランザクション・ラグが役立つのは、アプリケーションで通知に対するフロー制御を実装している場合のみです。ゼロ以外のトランザクション・ラグを使用する場合は、アプリケーションのワークロードのプロパティを、通知が妥当な頻度で生成されるように設定することをお薦めします。そうしないと、ラグに達するまで通知が無限に遅延する可能性があります。

TRANSACTION_LAGを指定すると、登録時にQOS_ROWIDSを指定した場合にも、通知メッセージにはROWIDレベルの粒度を使用できなくなります。

NTFN_GROUPING_CLASS

通知をグループ化するクラスを指定します。使用可能な値はDBMS_CQ_NOTIFICATION.NTFN_GROUPING_CLASS_TIME(通知を時間でグループ化)のみです。

NTFN_GROUPING_VALUE

グループを定義する時間間隔を秒単位で指定します。たとえば、この値が900の場合、同じ15分間隔内に生成された通知がグループ化されます。

NTFN_GROUPING_TYPE

次のいずれかのグループ化のタイプを指定します。

  • DBMS_CQ_NOTIFICATION.NTFN_GROUPING_TYPE_SUMMARY: グループ内のすべての通知は、単一の通知に要約されます。

  • DBMS_CQ_NOTIFICATION.NTFN_GROUPING_TYPE_LAST: グループ内の最後の通知のみが公開され、それより前の通知は破棄されます。

NTFN_GROUPING_START_TIME

通知生成の開始時間を指定します。NULLが指定されると、システム生成の現在の時間がデフォルトになります。

NTFN_GROUPING_REPEAT_COUNT

通知を繰り返す回数を指定します。登録の存続中に通知を永続的に受信するには、DBMS_CQ_NOTIFICATION.NTFN_GROUPING_FOREVERに設定します。登録の存続中に最大でnの通知を受信するには、nに設定します。


表11-3サービスのクオリティ・フラグは、DBMS_CQ_NOTIFICATIONパッケージ内の定数です。このフラグは、CQ_NOTIFICATION$_REG_INFOQOS_FLAGS属性を使用して指定できます(表11-2を参照)。

表11-3 サービスのクオリティ・フラグ

フラグ 説明

QOS_DEREG_NFY

最初の通知後に登録をパージします。

QOS_RELIABLE

通知を永続データベース・キューに格納します。

Oracle RAC環境では、データベース・インスタンスで障害が発生すると、正常なデータベース・インスタンスがキューにある通知メッセージを配信できます。

デフォルト: 通知はより効率のよい共有メモリーに格納されます。

QOS_ROWIDS

変更された各行のROWIDを通知に含めます。

QOS_QUERY

QRCNに対する問合せを登録します(「問合せ結果変更通知(QRCN)」を参照)。

QRCNに対する問合せを登録できない場合は、QOS_BEST_EFFORTも指定していないかぎり、登録時にエラーが生成されます。

デフォルト: OCNに対する問合せが登録されます(「オブジェクト変更通知(OCN)」を参照)。

QOS_BEST_EFFORT

QOS_QUERYと併用されます。問合せ結果変更の評価には複雑すぎる問合せの簡略バージョンを登録します。つまり、QRCNに対する問合せをベストエフォート・モードで登録します(「ベストエフォート・モード」を参照)。

どの問合せが簡略化されているかを確認するには、静的データ・ディクショナリ・ビューDBA_CQ_NOTIFICATION_QUERIESまたはUSER_CQ_NOTIFICATION_QUERIESを問い合せます。これらのビューでは、登録済の各問合せのQUERYIDとテキストが表示されます。

デフォルト: QRCNに対して問合せが保証モードで登録されます(「保証モード」を参照)。


登録済オブジェクトに変更があるたびに、プロシージャHR.dcn_callbackを起動する必要があるとします。例11-4では、HR.dcn_callbackが通知を受け取るように指定するCQ_NOTIFICATION$_REG_INFOオブジェクトを作成します。このオブジェクトを作成するには、DBMS_CQ_NOTIFICATIONパッケージに対するEXECUTE権限が必要です。

例11-4 CQ_NOTIFICATION$_REG_INFOオブジェクトの作成

DECLARE
  v_cn_addr CQ_NOTIFICATION$_REG_INFO;

BEGIN
  -- Create object:

  v_cn_addr := CQ_NOTIFICATION$_REG_INFO (
    'HR.dcn_callback',                 -- PL/SQL notification handler
    DBMS_CQ_NOTIFICATION.QOS_QUERY     -- notification type QRCN
    + DBMS_CQ_NOTIFICATION.QOS_ROWIDS, -- include rowids of changed objects
    0,                          -- registration persists until unregistered
    0,                          -- notify on all operations
    0                           -- notify immediately
    );

  -- Register queries: ...
END;
/

通知内の各問合せの識別

問合せの登録済リストに含まれる問合せにより、連続問合せ通知が生成される場合があります。特定の問合せによっていつ通知が生成されるかを確認するには、その問合せのSELECT構文のリストでDBMS_CQ_NOTIFICATION.CQ_NOTIFICATION_QUERYIDファンクションを使用します。次に例を示します。

SELECT EMPLOYEE_ID, SALARY, DBMS_CQ_NOTIFICATION.CQ_NOTIFICATION_QUERYID
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 10;

結果:

EMPLOYEE_ID     SALARY CQ_NOTIFICATION_QUERYID
----------- ---------- -----------------------
        200       2800                       0
 
1 row selected.

問合せによって通知が生成される場合、その通知には問合せIDが含まれます。

既存の登録への問合せの追加

問合せを既存の登録に追加する手順は、次のとおりです。

  1. 既存の登録の登録IDを取得します。

    これは、保存済の出力または*_CHANGE_NOTIFICATION_REGSの問合せから取得できます。

  2. 登録IDをパラメータとして使用し、プロシージャDBMS_CQ_NOTIFICATION.ENABLE_REGをコールして既存の登録をオープンします。

  3. 登録する問合せを実行します(DML操作またはDDL操作は実行しないでください)。

  4. DBMS_CQ_NOTIFICATION.REG_ENDファンクションを使用して登録をクローズします。

例11-5では、登録IDが21の既存の登録に問合せを追加します。

例11-5 既存の登録への問合せの追加

DECLARE
  v_cursor SYS_REFCURSOR;

BEGIN
  -- Open existing registration
  DBMS_CQ_NOTIFICATION.ENABLE_REG(21);
  OPEN v_cursor FOR
    -- Run query to be registered
    SELECT DEPARTMENT_ID
      FROM HR.DEPARTMENTS;  -- register this query
  CLOSE v_cursor;
  -- Close registration
  DBMS_CQ_NOTIFICATION.REG_END;
END;
/

CQN登録のベスト・プラクティス

CQNに最適なパフォーマンスを得るには、次の登録ガイドラインに従ってください。

  • 登録する問合せの数を少なくします。可能であれば、ほとんど変更されないオブジェクトを参照する問合せを登録します。

    オブジェクトの揮発性が非常に高いと、多数の通知が送信されることになり、そのオーバーヘッドによってOLTPスループットが低下します。

  • 同じ通知メッセージが複数の受信者宛に複製されないように、特定のオブジェクトについて重複登録の数を最小限に抑えます。

CQN登録のトラブルシューティング

登録を作成できない場合、または登録を作成しても予期した通知を受信していない場合は、次のような原因が考えられます。

  • JOB_QUEUE_PROCESSESパラメータがゼロ以外の値に設定されていません。

    このため、通知ハンドラを介してPL/SQL通知を受信できません。

  • 登録の作成時にSYSユーザーとして接続しました。

    CQN登録を作成するには、SYS以外のユーザーとして接続する必要があります。

  • 登録済オブジェクトを変更した後で、そのトランザクションをコミットしていません。

    通知は、トランザクションのコミット時にのみ生成されます。

  • 登録がデータベースに正常に作成されていません。

    確認するには、静的データ・ディクショナリ・ビュー*_CHANGE_NOTIFICATION_REGSを問い合せます。たとえば、次の文により、現行ユーザーに関するすべての登録と登録済オブジェクトが表示されます。

    SELECT REGID, TABLE_NAME FROM USER_CHANGE_NOTIFICATION_REGS;
    
  • 通知ハンドラの実行中に実行時エラーが発生しました。

    その場合は、プロシージャの実行を試行したJOBQプロセスのトレース・ファイルに記録されます。通常、トレース・ファイルの名前は次の形式になります。

    ORACLE_SID_jnumber_PID.trc
    

    たとえば、ORACLE_SIDがdbs1で、JOBQプロセスのプロセスID(PID)が12483の場合、トレース・ファイルの名前は通常、dbs1_j000_12483.trcとなります。

    通知ハンドラに'chnf_callback'、登録IDに100を指定して登録が作成されているとします。ここで、'chnf_callback'はデータベースに定義されていないとします。この場合、JOBQトレース・ファイルには次の書式のメッセージが含まれます。

    ****************************************************************************
       Run-time error during execution of PL/SQL cbk chnf_callback for reg CHNF100.
       Error in PLSQL notification of msgid:
       Queue :
       Consumer Name :
       PLSQL function :chnf_callback
       Exception Occured, Error msg:
       ORA-00604: error occurred at recursive SQL level 2
       ORA-06550: line 1, column 7: 
       PLS-00201: identifier 'CHNF_CALLBACK' must be declared
       ORA-06550: line 1, column 7:
       PL/SQL: Statement ignored
    ****************************************************************************
    

    通知ハンドラの実行中に実行時エラーが発生した場合は、実際に通知を受信していることを確認するために、簡略バージョンの通知ハンドラを作成してから、アプリケーション・ロジックを徐々に追加してください。

    非常に単純な通知ハンドラの例は次のとおりです。

    REM Create table in HR schema to hold count of notifications received.
    CREATE TABLE nfcount(cnt NUMBER);
    INSERT INTO nfcount (cnt) VALUES(0);
    COMMIT;
    CREATE OR REPLACE PROCEDURE chnf_callback
      (ntfnds IN CQ_NOTIFICATION$_DESCRIPTOR)
    IS
    BEGIN
      UPDATE nfcount SET cnt = cnt+1;
      COMMIT;
    END;
    /
    
  • トランザクションがコミットされてからエンド・ユーザーが通知を受信するまでに、タイム・ラグが発生しています。

CQN登録の問合せ

登録のQOSオプションなど、すべての登録に関するトップレベルの情報を確認するには、静的データ・ディクショナリ・ビュー*_CHANGE_NOTIFICATION_REGSを問い合せます。

たとえば、クライアントの登録IDと通知を受信するオブジェクトのリストを取得できます。HRの登録IDと表名を表示するには、次の問合せを使用します。

SELECT regid, table_name FROM USER_CHANGE_NOTIFICATION_REGS;

どの問合せがQRCNに対して登録されているかを確認するには、静的データ・ディクショナリ・ビューUSER_CQ_NOTIFICATION_QUERIESまたはDBA_CQ_NOTIFICATION_QUERIESを問い合せます。これらのビューには、問合せで使用されるバインド値に関する情報が含まれています。これらのビューでは、元の問合せのバインド値が、定数として問合せテキストに含まれます。問合せテキストは、登録済の元の問合せと同等ですが、同一ではない場合があります。


参照:

静的データ・ディクショナリ・ビューUSER_CHANGE_NOTIFICATION_REGSおよびDBA_CQ_NOTIFICATION_QUERIESの詳細は、『Oracle Databaseリファレンス』を参照してください。

通知の解析

トランザクションのコミット時に、データベースでは登録済オブジェクトがトランザクション中に変更されたかどうかが判別されます。変更されたと判別された場合、登録で指定されている通知ハンドラが実行されます。

内容は次のとおりです。

CQ_NOTIFICATION$_DESCRIPTORオブジェクトの解析

CQN登録で通知が生成されると、CQ_NOTIFICATION$_DESCRIPTORオブジェクトがデータベースから通知ハンドラに渡されます。通知ハンドラでは、データベース変更の詳細をCQ_NOTIFICATION$_DESCRIPTORオブジェクトの属性から検出できます。

SQL*Plusでは、SYSとして接続し、次の文を実行するとこれらの属性を表示できます。

DESC CQ_NOTIFICATION$_DESCRIPTOR

表11-4に、CQ_NOTIFICATION$_DESCRIPTORの属性の要約を示します。

表11-4 CQ_NOTIFICATION$_DESCRIPTORの属性

属性 説明

REGISTRATION_ID

登録時に戻された登録ID。

TRANSACTION_ID

変更を行ったトランザクションのID。

DBNAME

通知が生成されたデータベースの名前。

EVENT_TYPE

通知をトリガーするデータベース・イベント。たとえば、属性には様々なデータベース・イベントに対応する次の定数を含めることができます。

  • EVENT_NONE

  • EVENT_STARTUP(インスタンスの起動)

  • EVENT_SHUTDOWN(インスタンスの停止 - Oracle RACの場合は最後のインスタンスの停止)

  • EVENT_SHUTDOWN_ANY(Oracle RACの場合は任意のインスタンスの停止)

  • EVENT_DEREG(登録の削除)

  • EVENT_OBJCHANGE(登録済の表に対する変更)

  • EVENT_QUERYCHANGE(登録済の結果セットに対する変更)

NUMTABLES

変更された表の数。

TABLE_DESC_ARRAY

このフィールドは、OCN登録の場合にのみ存在します。QRCN登録の場合はNULLになります。

EVENT_TYPEEVENT_OBJCHANGEの場合は、タイプCQ_NOTIFICATION$_TABLEの表変更記述子のVARRAYとなり、それぞれが変更された表に対応します。CQ_NOTIFICATION$_TABLEの属性は、表11-5を参照してください。

前述以外の場合はNULLになります。

QUERY_DESC_ARRAY

このフィールドは、QRCN登録の場合にのみ存在します。OCN登録の場合はNULLになります。

EVENT_TYPEEVENT_QUERYCHANGEの場合は、タイプCQ_NOTIFICATION$_QUERYの結果セット変更記述子のVARRAYとなり、それぞれが変更された結果セットに対応します。CQ_NOTIFICATION$_QUERYの属性は、表11-6を参照してください。

前述以外の場合はNULLになります。


CQ_NOTIFICATION$_TABLEオブジェクトの解析

CQ_NOTIFICATION$_DESCRIPTORタイプには、タイプCQ_NOTIFICATION$_TABLEの表記述子のVARRAYを保持する属性TABLE_DESC_ARRAYが含まれています。

SQL*Plusでは、SYSとして接続し、次の文を実行するとこれらの属性を表示できます。

DESC CQ_NOTIFICATION$_TABLE

表11-5に、CQ_NOTIFICATION$_TABLEの属性の要約を示します。

表11-5 CQ_NOTIFICATION$_TABLEの属性

属性 指定 ...

OPFLAGS

変更があった表に対して実行された操作のタイプ。たとえば、属性には様々なデータベース操作に対応する次の定数を含めることができます。

  • ALL_ROWSは、DELETE *のように表全体に変更があるか、行レベルの粒度の情報が要求されないか、通知に使用できず、受信者は表全体が変更されたとみなす必要があることを示します。

  • UPDATEOPは更新を示します。

  • DELETEOPは削除を示します。

  • ALTEROPALTER TABLEを示します。

  • DROPOPDROP TABLEを示します。

  • UNKNOWNOPは不明な操作を示します。

TABLE_NAME

変更があった表の名前。

NUMROWS

変更があった行数。

ROW_DESC_ARRAY

タイプCQ_NOTIFICATION$_ROWの行記述子のVARRAY(表11-7を参照)。opflagsALL_ROWSが設定されていた場合、ROW_DESC_ARRAYメンバーはNULLです。


CQ_NOTIFICATION$_QUERYオブジェクトの解析

CQ_NOTIFICATION$_DESCRIPTORタイプには、タイプCQ_NOTIFICATION$_QUERYの結果セット変更記述子のVARRAYを保持する属性QUERY_DESC_ARRAYが含まれています。

SQL*Plusでは、SYSとして接続し、次の文を実行するとこれらの属性を表示できます。

DESC CQ_NOTIFICATION$_QUERY

表11-6に、CQ_NOTIFICATION$_QUERYの属性の要約を示します。

表11-6 CQ_NOTIFICATION$_QUERYの属性

属性 指定 ...

QUERYID

変更された問合せのID。

QUERYOP

問合せを変更した操作(EVENT_QUERYCHANGEまたはEVENT_DEREG)。

TABLE_DESC_ARRAY

タイプCQ_NOTIFICATION$_TABLEの表変更記述子のVARRAY(それぞれが結果セットの変更の原因となった変更済の表に対応)。CQ_NOTIFICATION$_TABLEの属性は、表11-5を参照してください。


CQ_NOTIFICATION$_ROWオブジェクトの解析

登録中にROWIDオプションが指定されると、CQ_NOTIFICATION$_TABLEタイプにはROW_DESC_ARRAY属性、つまり、変更された行のROWIDを含むタイプCQ_NOTIFICATION$_ROWVARRAYが設定されます。CQ_NOTIFICATION$_TABLEオブジェクトのOPFLAGSフィールドにALL_ROWSが設定されていた場合、ROWID情報は使用できません。

表11-7に、CQ_NOTIFICATION$_ROWの属性の要約を示します。

表11-7 CQ_NOTIFICATION$_ROWの属性

属性 指定 ...

OPFLAGS

変更があった表に対して実行された操作のタイプ。表11-5OPFLAGSの説明を参照してください。

ROW_ID

変更された行のROWID


登録の削除

登録を削除するには、登録IDをパラメータとして使用してプロシージャDBMS_CQ_NOTIFICATION.DEREGISTERをコールします。たとえば、次の文により、登録IDが21の登録が解除されます。

DBMS_CQ_NOTIFICATION.DEREGISTER(21);

登録を作成したユーザーまたはSYSユーザーのみが登録を解除できます。

CQNの構成: 使用例

この使用例では、開発者として従業員データ(名前、所在地、電話番号など)を提供するWebアプリケーションを管理しているとします。このアプリケーションはOracle Application Serverで実行され、使用量が多く、バックエンド・データベースにあるHR.EMPLOYEES表およびHR.DEPARTMENTS表の頻繁な問合せを処理します。この2つの表はあまり変更されないため、アプリケーションでは問合せ結果をキャッシュすることでパフォーマンスを改善できます。キャッシュにより、バックエンド・データベースへのラウンドトリップ、およびサーバー側での実行待機時間が回避されます。

DBMS_CQ_NOTIFICATIONパッケージを使用すると、HR.EMPLOYEES表およびHR.DEPARTMENTS表に基づく問合せを登録できます。CQNを構成する手順は、次のとおりです。

  1. 「PL/SQL通知ハンドラの作成」の説明に従って、通知を処理するサーバー側PL/SQLストアド・プロシージャを作成します。

  2. 「問合せの登録」の説明に従って、HR.EMPLOYEES表およびHR.DEPARTMENTS表へのQRCNに対する問合せを登録します。

これらの手順の完了後は、手順2で登録した問合せの結果に対する変更がコミットされると、手順1で作成した通知ハンドラによってWebアプリケーションに変更が通知され、この直後に、バックエンド・データベースの問合せによりWebアプリケーションでキャッシュがリフレッシュされます。

内容は次のとおりです。

PL/SQL通知ハンドラの作成

次の説明に従って、通知を処理するサーバー側ストアドPL/SQLプロシージャを作成します。

  1. AS SYSDBAでデータベースに接続します。

  2. 必要な権限をHRに付与します。

    GRANT EXECUTE ON DBMS_CQ_NOTIFICATION TO HR;
    GRANT CHANGE NOTIFICATION TO HR;
    
  3. 通知を受信するためにJOB_QUEUE_PROCESSESパラメータを有効化します。

    ALTER SYSTEM SET "JOB_QUEUE_PROCESSES"=4;
    
  4. SYS以外のユーザー(HRなど)としてデータベースに接続します。

  5. 受信した通知イベントのレコードを保持するデータベース表を作成します。

    -- Create table to record notification events.
    DROP TABLE nfevents;
    CREATE TABLE nfevents (
      regid      NUMBER,
      event_type NUMBER
    );
    
    -- Create table to record notification queries:
    DROP TABLE nfqueries;
    CREATE TABLE nfqueries (
      qid NUMBER,
      qop NUMBER
    );
    
    -- Create table to record changes to registered tables:
    DROP TABLE nftablechanges;
    CREATE TABLE nftablechanges (
      qid             NUMBER,
      table_name      VARCHAR2(100),
      table_operation NUMBER
    );
    
    -- Create table to record ROWIDs of changed rows:
    DROP TABLE nfrowchanges;
    CREATE TABLE nfrowchanges (
      qid        NUMBER,
      table_name VARCHAR2(100),
      row_id     VARCHAR2(2000)
    );
    
  6. 例11-6に示すように、プロシージャHR.chnf_callbackを作成します。

例11-6 サーバー側PL/SQL通知ハンドラの作成

CREATE OR REPLACE PROCEDURE chnf_callback (
  ntfnds IN CQ_NOTIFICATION$_DESCRIPTOR
)
IS
  regid           NUMBER;
  tbname          VARCHAR2(60);
  event_type      NUMBER;
  numtables       NUMBER;
  operation_type  NUMBER;
  numrows         NUMBER;
  row_id          VARCHAR2(2000);
  numqueries      NUMBER;
  qid             NUMBER;
  qop             NUMBER;

BEGIN
  regid := ntfnds.registration_id;
  event_type := ntfnds.event_type;

  INSERT INTO nfevents (regid, event_type)
  VALUES (chnf_callback.regid, chnf_callback.event_type);

  numqueries :=0;

  IF (event_type = DBMS_CQ_NOTIFICATION.EVENT_QUERYCHANGE) THEN
    numqueries := ntfnds.query_desc_array.count;

    FOR i IN 1..numqueries LOOP  -- loop over queries
      qid := ntfnds.query_desc_array(i).queryid;
      qop := ntfnds.query_desc_array(i).queryop;

      INSERT INTO nfqueries (qid, qop)
      VALUES(chnf_callback.qid, chnf_callback.qop);

      numtables := 0;
      numtables := ntfnds.query_desc_array(i).table_desc_array.count;

      FOR j IN 1..numtables LOOP  -- loop over tables
        tbname :=
          ntfnds.query_desc_array(i).table_desc_array(j).table_name;
        operation_type :=
          ntfnds.query_desc_array(i).table_desc_array(j).Opflags;

        INSERT INTO nftablechanges (qid, table_name, table_operation) 
        VALUES (
          chnf_callback.qid,
          tbname,
          operation_type
        );

        IF (bitand(operation_type, DBMS_CQ_NOTIFICATION.ALL_ROWS) = 0) THEN
          numrows := ntfnds.query_desc_array(i).table_desc_array(j).numrows;
        ELSE
          numrows :=0;  -- ROWID info not available
        END IF;

        -- Body of loop does not run when numrows is zero.
        FOR k IN 1..numrows LOOP  -- loop over rows
          Row_id :=
 ntfnds.query_desc_array(i).table_desc_array(j).row_desc_array(k).row_id;

          INSERT INTO nfrowchanges (qid, table_name, row_id)
          VALUES (chnf_callback.qid, tbname, chnf_callback.Row_id);

        END LOOP;  -- loop over rows
      END LOOP;  -- loop over tables
    END LOOP;  -- loop over queries
  END IF;
  COMMIT;
END;
/

問合せの登録

通知ハンドラの作成後に、例11-7に示すように、HR.chnf_callbackを通知ハンドラとして指定して、通知を受信する対象となる問合せを登録します。

例11-7 問合せの登録

DECLARE
  reginfo   CQ_NOTIFICATION$_REG_INFO;
  mgr_id    NUMBER;
  dept_id   NUMBER;
  v_cursor  SYS_REFCURSOR;
  regid     NUMBER;

BEGIN
  /* Register two queries for QRNC: */
  /* 1. Construct registration information.
        chnf_callback is name of notification handler.
        QOS_QUERY specifies result-set-change notifications. */

  reginfo := cq_notification$_reg_info (
    'chnf_callback',
    DBMS_CQ_NOTIFICATION.QOS_QUERY,
    0, 0, 0
  );

  /* 2. Create registration. */

  regid := DBMS_CQ_NOTIFICATION.new_reg_start(reginfo);

  OPEN v_cursor FOR
    SELECT dbms_cq_notification.CQ_NOTIFICATION_QUERYID, manager_id
    FROM HR.EMPLOYEES
    WHERE employee_id = 7902;
  CLOSE v_cursor;

  OPEN v_cursor FOR
    SELECT dbms_cq_notification.CQ_NOTIFICATION_QUERYID, department_id
    FROM HR.departments
    WHERE department_name = 'IT';
  CLOSE v_cursor;

  DBMS_CQ_NOTIFICATION.reg_end;
END;
/

新しく作成した登録を表示:

SELECT queryid, regid, TO_CHAR(querytext)
FROM user_cq_notification_queries;

次に類似した結果が得られます。

QUERYID REGID                               TO_CHAR(QUERYTEXT)
------- ----- ------------------------------------------------
     22    41 SELECT HR.DEPARTMENTS.DEPARTMENT_ID
                FROM HR.DEPARTMENTS
                  WHERE HR.DEPARTMENTS.DEPARTMENT_NAME  = 'IT'

     21    41 SELECT HR.EMPLOYEES.MANAGER_ID
                FROM HR.EMPLOYEES
                  WHERE HR.EMPLOYEES.EMPLOYEE_ID  = 7902

次のトランザクションを実行すると、QUERYIDが22の問合せの結果が変更されます。

UPDATE DEPARTMENTS
SET DEPARTMENT_NAME = 'FINANCE'
WHERE department_name = 'IT';

通知プロシージャchnf_callback(例11-6で作成したプロシージャ)が実行されます。

通知イベントが記録される表を問合せ:

SELECT * FROM nfevents;

次に類似した結果が得られます。

REGID EVENT_TYPE
----- ----------
   61          7

EVENT_TYPE 7は、EVENT_QUERYCHANGE(問合せ結果変更)に対応します。

登録済の表への変更が記録される表を問い合せます。

SELECT * FROM nftablechanges;

次に類似した結果が得られます。

REGID     TABLE_NAME TABLE_OPERATION
----- -------------- ---------------
   42 HR.DEPARTMENTS               4

TABLE_OPERATION 4は、UPDATEOP(更新操作)に対応します。

変更された行のROWIDが記録される表を問い合せます。

SELECT * FROM nfrowchanges;

次に類似した結果が得られます。

REGID     TABLE_NAME              ROWID
----- -------------- ------------------
   61 HR.DEPARTMENTS AAANkdAABAAALinAAF