連続問合せ通知(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が送信されます。
たとえば、アプリケーションで例11-1のOCNに対する問合せが登録され、EMPLOYEES
表を変更するトランザクションがユーザーによってコミットされると、変更された行が問合せの条件句を満たしていない場合でも(DEPARTMENT_ID
= 5の場合など)、データベースからアプリケーションにOCNが送信されます。
注意: QRCNを使用するには、データベースのCOMPATIBLE 初期化パラメータが11.0.0以上であり、自動UNDO管理(AUM)が有効(デフォルト設定)である必要があります。
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の問合せの次のような簡略バージョンが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
を指定します。
通知を生成するイベントは次のとおりです。
通知タイプがOCNの場合、1つ以上の登録済オブジェクトを変更するあらゆるDMLトランザクションで、コミット時に各オブジェクトに対して通知が1つ生成されます。
通知タイプがQRCNの場合、1つ以上の登録済問合せの結果を変更するあらゆるDMLトランザクションで、コミット時に通知が生成されます。この通知には、結果が変更された問合せのIDが含まれます。
どちらの通知タイプでも、通知には次の内容が含まれます。
変更された各表の名前
操作タイプ(INSERT
、UPDATE
またはDELETE
)
変更された各行のROWID
(ROWID
オプションを使用して登録が作成され、変更された行の数があまり多くない場合)。詳細は、「ROWIDオプション」を参照。
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文の結果として生成された場合
変更された表の名前の配列
操作タイプ(INSERT
、UPDATE
など)
通知には、変更されたデータ自体は含まれません。たとえば、5000から6000への月給の増額があっても、通知には示されません。変更されたオブジェクト、行または問合せ結果の最新の値を取得するには、アプリケーションからデータベースに問い合せる必要があります。
CQNに適したアプリケーションは、データベースへのネットワーク・ラウンドトリップを回避するために、変更の頻度の低いオブジェクトに対する問合せの結果セットを中間層にキャッシュするアプリケーションです。これらのアプリケーションでは、CQNを使用して、キャッシュされる問合せを登録できます。このようなアプリケーションは、通知を受信すると、登録済問合せを再実行してキャッシュをリフレッシュできます。
このようなアプリケーションの例としては、Webフォーラムがあります。Webフォーラムのユーザーは、コンテンツがデータベースに挿入されても、挿入後すぐにそのコンテンツを参照する必要はないため、このアプリケーションでは情報を中間層にキャッシュし、キャッシュをいつリフレッシュするかをCQNで指示できます。
図11-1に、データがデータベースから提供され、中間にキャッシュされた後、インターネット経由でアクセスされる一般的な使用例を示します。
中間層のアプリケーションは、キャッシュをデータベースと相対でできるかぎり最新の状態に保ちつつ、データベース・オブジェクトのキャッシュ・コピーに迅速にアクセスする必要があります。キャッシュ・データは、トランザクションでデータが変更されてコミットされると不要になるため、アプリケーションが不正な結果にアクセスする危険性があります。アプリケーションがCQNを使用している場合、データベースは、登録済オブジェクトに変更が発生した時点で変更内容の詳細を使用して通知を公開できます。この通知に応答して、アプリケーションではキャッシュ・データをバックエンド・データベースからフェッチしてリフレッシュできます。
図11-2に、中間層のWebクライアントが通知を受信して処理するプロセスを示します。
図11-2の各手順は次のとおりです(PL/SQLを使用して登録が作成され、アプリケーションによりHR
.EMPLOYEES
に対する問合せの結果セットがキャッシュされている場合)。
開発者は、PL/SQLを使用して、問合せに対するCQN登録を作成します。このプロセスでは、通知を処理するストアドPL/SQLプロシージャを作成した後、PL/SQL CQNインタフェースを使用して問合せに対する登録を作成し、作成したPL/SQLプロシージャを通知ハンドラとして指定します。
データベースでは、データ辞書に登録情報が移入されます。
ユーザーがバックエンド・データベースのHR
.EMPLOYEES
表の行を更新し、その更新をコミットすると、問合せ結果が変更されます。これで、中間層でキャッシュされていたHR
.EMPLOYEES
のデータが無効になります。
データベースにより、内部キューに変更を説明するメッセージが追加されます。
データベースからJOBQ
バックグラウンド・プロセスに、通知メッセージが通知されます。
JOBQ
プロセスにより、クライアント・アプリケーションから指定されたストアド・プロシージャが実行されます。この例では、JOBQ
からサーバー側PL/SQLプロシージャにデータが渡されます。PL/SQL通知ハンドラの実装により、通知の処理方法が決まります。
開発者は、サーバー側PL/SQLプロシージャ内に、登録済オブジェクトに対する変更を中間層のクライアント・アプリケーションに通知するための論理を実装できます。たとえば、HR
.EMPLOYEES
内で変更された行のROWID
をアプリケーションに通知します。
中間層のクライアント・アプリケーションでは、バックエンド・データベースを問い合せて、変更があった行のデータを取得します。
クライアント・アプリケーションにより、キャッシュがこのデータで更新されます。
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登録インタフェースは、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登録のデフォルトは、表11-1に示すオプションを使用して変更できます。
表11-1 連続問合せ通知登録オプション
オプション | 説明 |
---|---|
通知タイプ |
QRCNを指定します(デフォルトはOCN)。 |
QRCNモード脚注1 |
ベストエフォート・モードを指定します(デフォルトは保証モード)。 |
|
変更された各行の |
操作フィルタ脚注2 |
指定したフィルタ条件を操作タイプが満たした場合のみ、通知を公開します。 |
トランザクション・ラグ脚注2 |
非推奨。かわりに通知グループ化を使用してください。 |
通知グループ化 |
通知のグループ化方法を指定します。 |
信頼可能 |
通知を(デフォルトの共有メモリーではなく)永続データベース・キューに格納します。 |
通知時にパージ |
最初の通知後に登録をパージします。 |
タイムアウト |
指定の時間間隔後に登録をパージします。 |
脚注1 通知タイプがQRCNの場合にのみ適用されます。
脚注2 通知タイプがOCNの場合にのみ適用されます。
内容は次のとおりです。
通知タイプは、OCN(「オブジェクト変更通知(OCN)」を参照)およびQRCN(「問合せ結果変更通知(QRCN)」を参照)です。
QRCNモード・オプションは、通知タイプがQRCNの場合にのみ適用されます。通知タイプをQRCNに設定する手順は、「「通知タイプ」オプション」を参照してください。
QRCNモードには、保証モード(「保証モード」を参照)とベストエフォート・モード(「ベストエフォート・モード」を参照)があります。
デフォルトは保証モードです。ベストエフォート・モードの場合は、CQ_NOTIFICATION$_REG_INFO
オブジェクトのQOSFLAGS
属性にQOS_BEST_EFFORT
を指定します。
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の場合にのみ適用されます。
操作フィルタ・オプションを使用すると、通知を生成する操作のタイプを指定できます。
デフォルトは全操作です。一部の操作でのみ通知が生成されるように指定するには、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の場合にのみ適用されます。
トランザクション・ラグ・オプションでは、クライアント・アプリケーションがデータベースから遅れることのできるトランザクション数を指定します。数が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 |
次のいずれかのグループ化のタイプを指定します。
|
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登録を作成するための前提条件は次のとおりです。
次の権限が必要です。
DBMS_CQ_NOTIFICATION
パッケージのEXECUTE
権限(登録の作成にこのパッケージのサブプログラムを使用)
CHANGE
NOTIFICATION
システム権限
登録するすべてのオブジェクトに対するSELECT
権限
登録済の問合せに関連付けられているオブジェクトに対する権限を失うと、通知が生成されます(「登録解除」を参照)。
SYS以外のユーザーとして接続する必要があります。
コミットされていないトランザクションの途中でない必要があります。
dml_locks
init
.ora
パラメータの値がゼロ以外である必要があります(デフォルト値はゼロ以外です)。
(これは、通知を受信するための前提条件でもあります。)
注意: QRCNを使用するには、データベースのCOMPATIBLE 設定が11.0.0以上である必要があります。 |
ストアド・プロシージャやREF
カーソルの一部として実行される問合せなど、ほとんどの問合せをOCNに対して登録できます。
OCNに対して登録不可能な問合せは次のとおりです。
固定表または固定ビューに対する問合せ
ユーザー・ビューに対する問合せ
データベース・リンク(dblink)を含む問合せ
マテリアライズド・ビューでの問合せ
注意: OCN登録ではシノニムを使用できますが、QRCN登録では使用できません。 |
QRCNに対して保証モードで登録可能な問合せ、QRCNに対してベストエフォート・モードでのみ登録可能な問合せ、およびQRCNに対してどちらのモードでも登録不可能な問合せがあります。(モードの詳細は、「保証モード」および「ベストエフォート・モード」を参照してください。)
内容は次のとおりです。
問合せを保証モードでQRCNに対して登録するには、問合せを次のルールに準拠させる必要があります。
参照するすべての列がNUMBER
またはVARCHAR2
データ型である必要があります。
列の式に含まれる算術演算子が次のバイナリ演算子に制限され、そのオペランドが数値データ型の列である必要があります。
+
(加算)
-
(減算、単項マイナスではない)
*
(乗算)
/
(除算)
条件句の比較演算子は次の演算子に制限されます。
<
(より小さい)
<=
(以下)
=
(等しい)
>=
(以上)
>
(より大きい)
<>
または!=
(等しくない)
IS
NULL
IS
NOT
NULL
条件句のBoolean演算子はAND
、OR
およびNOT
に制限されます。
問合せに集計関数(SUM
、COUNT
、AVERAGE
、MIN
、MAX
など)は含められません。
SQL集計関数のリストについては、『Oracle Database SQL言語リファレンス』を参照してください。
保証モードでは、単一表および一部の内部等価結合に対するほとんどの問合せが可能です(次の例を参照)。
SELECT SALARY FROM EMPLOYEES, DEPARTMENTS WHERE EMPLOYEES.DEPARTMENT_ID = DEPARTMENTS.DEPARTMENT_ID AND DEPARTMENTS.LOCATION_ID = 1700;
注意:
|
次のいずれかの条件を満たす問合せは、ベストエフォート・モードでのみQRCNに対して登録可能であり、その簡略バージョンでは通知がオブジェクトの粒度で生成されます。
暗号化が有効にされている列を参照する問合せ
同じ型の項目がSELECT
構文のリストに11以上ある問合せ
次のいずれかを使用した式を含む問合せ
文字列関数(SUBSTR
、LTRIM
、RTRIM
など)
算術関数(TRUNC
、ABS
、SQRT
など)
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に対して登録不可能です。
ビュー
固定表、リモート表または仮想プライベート・データベース(VPD)ポリシーが有効化されている表
DUAL
(SELECT
構文のリスト内)
シノニム
ユーザー定義のPL/SQLサブプログラムのコール
「保証モードでQRCNに対して登録可能な問合せ」にリストされていない演算子
集計関数COUNT
(他の集計関数は、ベストエフォート・モードでは登録可能ですが、保証モードでは登録不可能です。)
アプリケーション・コンテキスト(次の例を参照)
SELECT SALARY FROM EMPLOYEES WHERE USER = SYS_CONTEXT('USERENV', 'SESSION_USER');
SYSDATE
、SYSTIMESTAMP
またはCURRENT
TIMESTAMP
また、マテリアライズド・ビューを使用して問合せオプティマイザがリライトした問合せはQRCNに対して登録できません。問合せオプティマイザの詳細は、『Oracle Databaseパフォーマンス・チューニング・ガイド』を参照してください。
PL/SQLを使用してCQN登録を作成する手順は、次のとおりです。
通知ハンドラとして機能するストアドPL/SQLプロシージャを作成します。
通知ハンドラの名前、通知タイプ、および登録のその他の属性を指定するCQ_NOTIFICATION$_REG_INFO
オブジェクトを作成します。
クライアント・アプリケーションで、DBMS_CQ_NOTIFICATION
.NEW_REG_START
ファンクションを使用して登録ブロックをオープンします。
登録する問合せを実行します(DML操作またはDDL操作は実行しないでください)。
DBMS_CQ_NOTIFICATION
.REG_END
ファンクションを使用して登録ブロックをクローズします。
内容は次のとおりです。
参照: CQ_NOTIFICATION$_REG_INFOオブジェクトとファンクションNEW_REG_STARTおよびREG_END の詳細は、 『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』 を参照してください。それらすべてはDBMS_CQ_NOTIFICATION パッケージで定義されています。 |
通知ハンドラとして使用するPL/SQLストアド・プロシージャの作成時には、次のシグネチャを含める必要があります。
PROCEDURE schema_name.proc_name(ntfnds IN CQ_NOTIFICATION$_DESCRIPTOR)
このシグネチャで、schema_name
はデータベース・スキーマ名、proc_name
はストアド・プロシージャ名、ntfnds
は通知記述子を示します。
通知記述子はCQ_NOTIFICATION$_DESCRIPTOR
オブジェクトであり、その属性によって変更の詳細(トランザクションID、変更のタイプ、影響を受けた問合せ、変更された表など)が記述されます。
通知記述子ntfnds
はJOBQ
プロセスから通知ハンドラproc_name
に渡され、このハンドラがアプリケーション要件に従って通知を処理します。(これは図11-2の手順6に示します。)
注意: 通知ハンドラは、ジョブ・キュー・プロセス内で実行されます。JOB_QUEUE_PROCESSES 初期化パラメータでは、ジョブの実行用に作成できるプロセスの最大数を指定します。PL/SQL通知を受信するには、JOB_QUEUE_PROCESSES をゼロ以外の値に設定する必要があります。 |
タイプCQ_NOTIFICATION$_REG_INFO
のオブジェクトでは、登録済オブジェクトの変更時にデータベースで実行される通知ハンドラを指定します。SQL*Plusでは、次の文を実行してそのタイプ属性を表示できます。
DESC CQ_NOTIFICATION$_REG_INFO
表11-2に、SYS
.CQ_NOTIFICATION$_REG_INFO
の属性を示します。
表11-2 CQ_NOTIFICATION$_REG_INFOの属性
属性 | 説明 |
---|---|
|
通知の生成時に実行されるPL/SQLプロシージャ(通知ハンドラ)の名前を指定します。この名前は、 |
|
1つ以上のサービスのクオリティ・フラグ( 複数のサービスのクオリティ・フラグを指定するには、ビット単位の |
|
登録のタイムアウト期間を指定します。0(ゼロ)以外の値に設定する場合は、データベースにより登録がパージされるまでの秒数を指定します。
|
|
OCN(「オブジェクト変更通知(OCN)」を参照)にのみ適用されます。 SQL文の型に基づいてメッセージをフィルタリングします。
ビット単位の |
|
非推奨。フロー制御の通知を実装するには、 OCN(「オブジェクト変更通知(OCN)」を参照)にのみ適用されます。 クライアントがデータベースから遅れることのできるトランザクション数またはデータベース変更数を指定します。0の場合、クライアントは無効化メッセージを生成直後に受信します。5の場合、登録済オブジェクトを変更するトランザクションのうち5番目ごとに通知が送信されます。データベースでは、中間の変更がオブジェクトの粒度で追跡され、変更が通知とともにバンドルされます。そのため、クライアントから中間の変更が失われることはありません。 トランザクションのコミット時にオブジェクトの変更通知をそれ以上の遅延なしで受信する必要のあるほとんどのアプリケーションでは、トランザクション・ラグ0(ゼロ)を選択するように期待されます。ゼロ以外のトランザクション・ラグが役立つのは、アプリケーションで通知に対するフロー制御を実装している場合のみです。ゼロ以外のトランザクション・ラグを使用する場合は、アプリケーションのワークロードのプロパティを、通知が妥当な頻度で生成されるように設定することをお薦めします。そうしないと、ラグに達するまで通知が無限に遅延する可能性があります。
|
|
通知をグループ化するクラスを指定します。使用可能な値は |
|
グループを定義する時間間隔を秒単位で指定します。たとえば、この値が900の場合、同じ15分間隔内に生成された通知がグループ化されます。 |
|
次のいずれかのグループ化のタイプを指定します。
|
|
通知生成の開始時間を指定します。 |
|
通知を繰り返す回数を指定します。登録の存続中に通知を永続的に受信するには、 |
表11-3のサービスのクオリティ・フラグは、DBMS_CQ_NOTIFICATION
パッケージ内の定数です。このフラグは、CQ_NOTIFICATION$_REG_INFO
のQOS_FLAGS
属性を使用して指定できます(表11-2を参照)。
表11-3 サービスのクオリティ・フラグ
フラグ | 説明 |
---|---|
|
最初の通知後に登録をパージします。 |
|
通知を永続データベース・キューに格納します。 Oracle RAC環境では、データベース・インスタンスで障害が発生すると、正常なデータベース・インスタンスがキューにある通知メッセージを配信できます。 デフォルト: 通知はより効率のよい共有メモリーに格納されます。 |
|
変更された各行の |
|
QRCNに対する問合せを登録します(「問合せ結果変更通知(QRCN)」を参照)。 QRCNに対する問合せを登録できない場合は、 デフォルト: OCNに対する問合せが登録されます(「オブジェクト変更通知(OCN)」を参照)。 |
|
どの問合せが簡略化されているかを確認するには、静的データ・ディクショナリ・ビュー デフォルト: 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が含まれます。
問合せを既存の登録に追加する手順は、次のとおりです。
既存の登録の登録IDを取得します。
これは、保存済の出力または*_CHANGE_NOTIFICATION_REGS
の問合せから取得できます。
登録IDをパラメータとして使用し、プロシージャDBMS_CQ_NOTIFICATION
.ENABLE_REG
をコールして既存の登録をオープンします。
登録する問合せを実行します(DML操作またはDDL操作は実行しないでください)。
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に最適なパフォーマンスを得るには、次の登録ガイドラインに従ってください。
登録する問合せの数を少なくします。可能であれば、ほとんど変更されないオブジェクトを参照する問合せを登録します。
オブジェクトの揮発性が非常に高いと、多数の通知が送信されることになり、そのオーバーヘッドによってOLTPスループットが低下します。
同じ通知メッセージが複数の受信者宛に複製されないように、特定のオブジェクトについて重複登録の数を最小限に抑えます。
登録を作成できない場合、または登録を作成しても予期した通知を受信していない場合は、次のような原因が考えられます。
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; /
トランザクションがコミットされてからエンド・ユーザーが通知を受信するまでに、タイム・ラグが発生しています。
登録の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リファレンス』を参照してください。 |
トランザクションのコミット時に、データベースでは登録済オブジェクトがトランザクション中に変更されたかどうかが判別されます。変更されたと判別された場合、登録で指定されている通知ハンドラが実行されます。
内容は次のとおりです。
CQN登録で通知が生成されると、CQ_NOTIFICATION$_DESCRIPTOR
オブジェクトがデータベースから通知ハンドラに渡されます。通知ハンドラでは、データベース変更の詳細をCQ_NOTIFICATION$_DESCRIPTOR
オブジェクトの属性から検出できます。
SQL*Plusでは、SYS
として接続し、次の文を実行するとこれらの属性を表示できます。
DESC CQ_NOTIFICATION$_DESCRIPTOR
表11-4に、CQ_NOTIFICATION$_DESCRIPTOR
の属性の要約を示します。
表11-4 CQ_NOTIFICATION$_DESCRIPTORの属性
属性 | 説明 |
---|---|
|
登録時に戻された登録ID。 |
|
変更を行ったトランザクションのID。 |
|
通知が生成されたデータベースの名前。 |
|
通知をトリガーするデータベース・イベント。たとえば、属性には様々なデータベース・イベントに対応する次の定数を含めることができます。
|
|
変更された表の数。 |
|
このフィールドは、OCN登録の場合にのみ存在します。QRCN登録の場合は
前述以外の場合は |
|
このフィールドは、QRCN登録の場合にのみ存在します。OCN登録の場合は
前述以外の場合は |
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の属性
属性 | 指定 ... |
---|---|
|
変更があった表に対して実行された操作のタイプ。たとえば、属性には様々なデータベース操作に対応する次の定数を含めることができます。
|
|
変更があった表の名前。 |
|
変更があった行数。 |
|
タイプ |
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の属性
属性 | 指定 ... |
---|---|
|
変更された問合せのID。 |
|
問合せを変更した操作( |
|
タイプ |
登録中にROWID
オプションが指定されると、CQ_NOTIFICATION$_TABLE
タイプにはROW_DESC_ARRAY
属性、つまり、変更された行のROWID
を含むタイプCQ_NOTIFICATION$_ROW
のVARRAY
が設定されます。CQ_NOTIFICATION$_TABLE
オブジェクトのOPFLAGS
フィールドにALL_ROWS
が設定されていた場合、ROWID
情報は使用できません。
表11-7に、CQ_NOTIFICATION$_ROW
の属性の要約を示します。
表11-7 CQ_NOTIFICATION$_ROWの属性
属性 | 指定 ... |
---|---|
|
変更があった表に対して実行された操作のタイプ。 |
|
変更された行の |
登録を削除するには、登録IDをパラメータとして使用してプロシージャDBMS_CQ_NOTIFICATION
.DEREGISTER
をコールします。たとえば、次の文により、登録IDが21の登録が解除されます。
DBMS_CQ_NOTIFICATION.DEREGISTER(21);
登録を作成したユーザーまたはSYSユーザーのみが登録を解除できます。
この使用例では、開発者として従業員データ(名前、所在地、電話番号など)を提供するWebアプリケーションを管理しているとします。このアプリケーションはOracle Application Serverで実行され、使用量が多く、バックエンド・データベースにあるHR
.EMPLOYEES
表およびHR
.DEPARTMENTS
表の頻繁な問合せを処理します。この2つの表はあまり変更されないため、アプリケーションでは問合せ結果をキャッシュすることでパフォーマンスを改善できます。キャッシュにより、バックエンド・データベースへのラウンドトリップ、およびサーバー側での実行待機時間が回避されます。
DBMS_CQ_NOTIFICATION
パッケージを使用すると、HR
.EMPLOYEES
表およびHR
.DEPARTMENTS
表に基づく問合せを登録できます。CQNを構成する手順は、次のとおりです。
「PL/SQL通知ハンドラの作成」の説明に従って、通知を処理するサーバー側PL/SQLストアド・プロシージャを作成します。
「問合せの登録」
の説明に従って、HR
.EMPLOYEES
表およびHR
.DEPARTMENTS表へのQRCNに対する問合せを登録します。
これらの手順の完了後は、手順2で登録した問合せの結果に対する変更がコミットされると、手順1で作成した通知ハンドラによってWebアプリケーションに変更が通知され、この直後に、バックエンド・データベースの問合せによりWebアプリケーションでキャッシュがリフレッシュされます。
内容は次のとおりです。
次の説明に従って、通知を処理するサーバー側ストアドPL/SQLプロシージャを作成します。
AS
SYSDBA
でデータベースに接続します。
必要な権限をHR
に付与します。
GRANT EXECUTE ON DBMS_CQ_NOTIFICATION TO HR; GRANT CHANGE NOTIFICATION TO HR;
通知を受信するためにJOB_QUEUE_PROCESSES
パラメータを有効化します。
ALTER SYSTEM SET "JOB_QUEUE_PROCESSES"=4;
SYS以外のユーザー(HR
など)としてデータベースに接続します。
受信した通知イベントのレコードを保持するデータベース表を作成します。
-- 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) );
例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