8 キューの高度な概念

次の各項では、キューでのメッセージのステージングやキュー間でのメッセージの伝播の概念について説明します。

8.1 保護キュー

保護キューは、エンキューやデキューなどのキュー操作を実行できる1人以上のデータベース・ユーザーにOracle Databaseアドバンスト・キューイング(AQ)・エージェントを明示的に関連付ける必要があるキューです。保護キューの所有者はキューに対してすべてのキュー操作を実行できますが、他のユーザーは保護キュー・ユーザーとして構成されていないかぎり、保護キューに対するキュー操作を実行できません。Oracle Streamsでは、保護キューを使用して、適切なユーザーおよびOracle Streamsクライアントのみがメッセージのエンキューとデキューを確実に行うことができます。

8.1.1 保護キューおよびSET_UP_QUEUEプロシージャ

DBMS_STREAMS_ADMパッケージのSET_UP_QUEUEプロシージャを使用して作成されたすべてのANYDATAキューは、保護キューです。SET_UP_QUEUEプロシージャを使用してキューを作成すると、queue_userパラメータで指定したユーザーは、可能であればキューの保護キュー・ユーザーとして自動的に構成されます。また、キュー・ユーザーには、キューに対するENQUEUEおよびDEQUEUE権限が付与されます。メッセージをエンキューおよびデキューするには、キュー・ユーザーはDBMS_STREAMS_MESSAGINGパッケージまたはDBMS_AQ パッケージのEXECUTE権限も必要です。SET_UP_QUEUEプロシージャでは、これらのいずれの権限も付与されません。また、メッセージは、デキューできるサブスクライバが構成されるまで、キューにエンキューできません。

キュー・ユーザーを保護キュー・ユーザーとして構成するために、SET_UP_QUEUEプロシージャでは、存在しない場合はユーザー名と同じ名前でOracle Streams AQエージェントが作成されます。ユーザーは、このエージェントを使用してキューに対するキュー操作を実行する必要があります。この名前のエージェントがすでに存在し、そのキュー・ユーザーのみに関連付けられている場合は、既存のエージェントが使用されます。SET_UP_QUEUEでは、エージェントとユーザーを指定して、DBMS_AQADMパッケージのENABLE_DB_ACCESSプロシージャが実行されます。

DBMS_STREAMS_ADMパッケージのSET_UP_QUEUEプロシージャを使用して保護キューを作成し、キュー所有者ではなくqueue_userパラメータで指定していないユーザーに、キューに対する操作の実行を許可する必要がある場合は、そのユーザーを手動でキューの保護キュー・ユーザーとして構成できます。また、SET_UP_QUEUEプロシージャを再実行して、キューに異なるqueue_userを指定することもできます。この場合、SET_UP_QUEUEではキューの作成をスキップしますが、queue_userで指定したユーザーがキューの保護キュー・ユーザーとして構成されます。

DBMS_AQADMパッケージを使用してANYDATAキューを作成する場合は、CREATE_QUEUE_TABLEプロシージャを実行するときにsecureパラメータを使用して、キューが保護キューかどうかを指定します。このプロシージャを実行するときにsecureパラメータにTRUEを指定すると、キューは保護キューになります。DBMS_AQADMパッケージを使用して保護キューを作成し、ユーザーが保護キューに対してキュー操作を実行できるようにする必要がある場合は、これらの保護キュー・ユーザーを手動で構成する必要があります。

8.1.2 保護キューおよびOracle Streamsクライアント

取得プロセスまたは適用プロセスを作成すると、Oracle Streamsプロセスに関連付けられている保護キューのOracle Streams AQエージェントが自動的に構成され、Oracle Streamsプロセスを実行するユーザーは、このキューの保護キュー・ユーザーとして自動的に指定されます。したがって、取得プロセスは保護キューを自動的にエンキューするように構成され、適用プロセスは保護キューから自動的にデキューするように構成されます。どちらの場合も、Oracle Streams AQエージェントの名前はOracle Streamsクライアントと同じになります。

取得プロセスの場合は、capture_userとして指定したユーザーが、取得プロセスを実行するユーザーとなります。適用プロセスの場合は、apply_userとして指定したユーザーが、適用プロセスを実行するユーザーとなります。capture_userまたはapply_userを指定しなければ、Oracle Streamsプロセスの作成プロシージャを起動したユーザーが、Oracle Streamsプロセスを実行するユーザーとなります。

同期取得を作成すると、同期取得と同じ名前を持つ保護キューのOracle Streams AQエージェントは、capture_userに指定されたユーザーに関連付けられます。capture_userが指定されていない場合は、同期取得を作成するプロシージャを起動したユーザーがcapture_userになります。capture_userは、このキューの保護キュー・ユーザーとして自動的に指定されます。そのため、同期取得では、保護キューを自動的にエンキューできます。

取得プロセスまたは同期取得のcapture_user、あるいは適用プロセスのapply_userを変更すると、指定したcapture_userまたはapply_userはOracle Streamsクライアントで使用されるキューの保護キュー・ユーザーとして構成されます。ただし、古い取得ユーザーまたは適用ユーザーは、キューの保護キュー・ユーザーとして構成されたままです。古いユーザーを削除するには、そのユーザーと関連するOracle Streams AQエージェントを指定して、DBMS_AQADMパッケージのDISABLE_DB_ACCESSプロシージャを実行します。また、不要になったエージェントは削除できます。DBA_AQ_AGENT_PRIVSデータ・ディクショナリ・ビューを問い合せると、Oracle Streams AQエージェントとその関連ユーザーを表示できます。

メッセージ・クライアントを作成すると、メッセージ・クライアントと同じ名前の保護キューのOracle Streams AQエージェントは、メッセージ・クライアントの作成プロシージャを実行するユーザーに関連付けられます。このメッセージ・クライアント・ユーザーは、このキューの保護キュー・ユーザーとして自動的に指定されます。そのため、このユーザーはメッセージ・クライアントを使用して、キューからメッセージをデキューできます。

取得プロセス、同期取得、適用プロセスまたはメッセージ・クライアントは、1ユーザーのみに関連付けることができます。ただし、ユーザーは、複数の取得プロセス、同期取得、適用プロセスおよびメッセージ・クライアントを含む複数のOracle Streamsクライアントに関連付けることができます。たとえば、適用プロセスに適用ユーザーとしてhroeの両方を含めることはできませんが、hrを複数の適用プロセスの適用ユーザーにすることはできます。

取得プロセス、同期取得、適用プロセスまたはメッセージ・クライアントを削除しても、これらのOracle Streamsクライアントの保護キュー・ユーザーとして構成されていたユーザーは、引き続きキューの保護キュー・ユーザーのままです。保護キュー・ユーザーとしてのユーザーを削除するには、ユーザーごとにDBMS_AQADMパッケージのDISABLE_DB_ACCESSプロシージャを実行します。また、不要になったエージェントは削除できます。

注意:

伝播および保護キューについては構成は必要ありません。つまり、伝播の削除時に、伝播のキューから保護キュー・ユーザーを削除するための追加の手順は必要ありません。

関連項目:

8.2 トランザクション・キューと非トランザクション・キュー

トランザクション・キューは、複数のメッセージを1つのトランザクションとして適用されるセットにグループ化できるキューです。つまり、適用プロセスでは、グループ内のすべてのメッセージを適用した後にCOMMITを実行します。非トランザクション・キューは、各メッセージが個別のトランザクションであるキューです。つまり、適用プロセスは、各メッセージが適用された後に、COMMITを実行します。どちらの場合も、メッセージはLCRまたはユーザー・メッセージのいずれかです。

DBMS_STREAMS_ADMパッケージのSET_UP_QUEUEプロシージャでは、常にトランザクション・キューが作成されます。トランザクション・キューと非トランザクション・キューの違いが重要になるのは、アプリケーション、同期取得または適用プロセスによってエンキューされたメッセージに対してのみです。適用プロセスは、常にソース・データベースで実行されたトランザクションが保つトランザクション内で取得LCRを適用します。

表8-1に、メッセージ・タイプとキューの型ごとに、適用プロセスの動作を示します。

表8-1 トランザクション・キューと非トランザクション・キューに対する適用プロセスの動作

メッセージ・タイプ トランザクション・キュー 非トランザクション・キュー

取得LCR

適用プロセスは元のトランザクションを保持します。

適用プロセスは元のトランザクションを保持します。

永続LCRまたは永続ユーザー・メッセージ

ユーザーが指定したメッセージのグループを、1つのトランザクションとして適用します。

各メッセージをそれぞれのトランザクション内で適用します。

ソース・データベースで実行されたトランザクションを保持する必要がある場合は、トランザクション・キューを使用してメッセージを格納します。同期取得で取得されたLCRがトランザクション・キューに格納されていることを確認します。

関連項目:

8.3 コミット時間キュー

永続キュー内のメッセージが参照またはデキューされる順序を制御できます。キュー内のメッセージの順序付けは、キュー表によって決定されます。キュー表の作成時にキュー表に対してメッセージの順序を指定できます。具体的には、DBMS_AQADM.CREATE_QUEUE_TABLEプロシージャのsort_listパラメータによって、メッセージの順序付けの方法が決定されます。コミット時間キュー内の各メッセージは、それぞれのメッセージをエンキューするトランザクションのコミット時に取得される近似コミット・システム変更番号(近似CSCN)によって順序付けされます。

コミット時間による順序付けはキュー表に対して指定され、そのキュー表を使用するキューをコミット時間キューと呼びます。DBMS_AQADM.CREATE_QUEUE_TABLEプロシージャのsort_listパラメータにcommit_timeを指定すると、生成されるキュー表でコミット時間による順序付けが使用されます。

Oracle Database 10g リリース2以上では、DBMS_STREAMS_ADMパッケージのSET_UP_QUEUEプロシージャによって作成されるキュー表のsort_listは、デフォルトで、commit_timeに設定されています。Oracle Database 10g リリース2より前のリリースでは、デフォルトで、enq_timeに設定されています(詳細は、次の項を参照)。SET_UP_QUEUEプロシージャのqueue_tableパラメータに既存のキュー表が指定されている場合、SET_UP_QUEUEによって作成されるキュー内でのメッセージの順序付けは、既存のキュー表によって決定されます。

注意:

同期取得では、トランザクションが確実に順序付けされるように、常にコミット時間キューにエンキューします。

8.3.1 コミット時間キューを使用する場合

Oracle Database内のキューにメッセージをエンキューすることによって、ユーザーまたはアプリケーションが情報を共有できます。エンキューされたメッセージは、単一のデータベース内で共有したり、他のデータベースに伝播することができます。メッセージは、LCRの場合とユーザー・メッセージの場合があります。たとえば、アプリケーション固有のメッセージが発生した場合や、データベースの変更に対してトリガーが起動された場合に、メッセージをエンキューできます。また、異機種間環境では、Oracle以外のデータベースで発生したメッセージを、アプリケーションでOracle Databaseでエンキューできます。

CREATE_QUEUE_TABLEプロシージャのsort_listパラメータには、commit_timeの他に、priorityenq­_timeを設定できます。priorityを設定すると、エンキュー時に指定された優先順位の高いものから順にメッセージが順序付けされます。enq_timeを設定すると、エンキューされた時間の古いものから順にメッセージが順序付けされます。

コミット時間キューは、環境でメッセージの同時エンキューに対して次のいずれかの要件をサポートする必要がある場合に役立ちます。

コミット時間キューでは、これらの要件がサポートされます。優先順位またはエンキュー時間による順序付けでは、トランザクション間の依存性の違反および一貫性のない参照が許可されるため、いずれの順序付けでもこれらの要件はサポートされません。これらの設定では、元の依存性にかかわらずメッセージがデキューされるため、トランザクションの間の依存性の違反が許可されます。また、これらの設定では、デキュー操作を伴わずに実行される複数の参照によってメッセージの様々なセットが生成されるため、キュー内のメッセージの一貫性のない参照が許可されます。

8.3.1.1 デキュー時のトランザクション間の依存性による順序付け

1つのデータベース・トランザクションを正常にコミットするために別のデータベース・トランザクションのコミットを必要とする場合、トランザクション間の依存性が発生します。データベース・トランザクションに関する情報を含むメッセージをエンキューできます。たとえば、データベース・トリガーによってメッセージのエンキューを実行できます。図8-1に、エンキュー時間による順序付けで、これらのメッセージのデキュー時にトランザクション間の依存性による順序付けがサポートされないことを示します。

図8-1 デキュー時のトランザクション間の依存性の違反

図8-1の説明が続きます
「図8-1 デキュー時のトランザクション間の依存性の違反」の説明

図8-1に、エンキュー時間による順序付けで、トランザクション間の依存性による順序付けが違反される場合があることを示します。メッセージe2をエンキューしたトランザクションは、メッセージe1およびe3をエンキューしたトランザクションがコミットされる前にコミットされています。メッセージe3に含まれる更新は、メッセージe2に含まれる挿入に依存しています。そのため、トランザクション間の依存性をサポートする正しいデキュー順序は、e2e1e3になります。ただし、エンキュー時間による順序付けでは、e2の前にe3をデキューできます。そのため、e3のデキュー時に、e3に含まれる変更をアプリケーションがhr.employees表に適用しようとすると、エラーが発生します。また、3つのメッセージがすべてデキューされた後、e3に含まれる変更が実行されていないために、hr.employees表の行に誤った情報が含まれています。

8.3.1.2 キュー内のメッセージの一貫性のある参照

図8-2に、エンキュー時間による順序付けで、キュー内のメッセージの一貫性のある参照がサポートされないことを示します。

図8-2 キュー内のメッセージの一貫性のない参照

図8-2の説明が続きます
「図8-2 キュー内のメッセージの一貫性のない参照」の説明

図8-2に、エンキュー時間による順序付けで、クライアントがキュー内のメッセージを参照するときに一定の順序が保証されないことを示します。セッション1および2は、メッセージをエンキューしている同時セッションです。セッション3は、エンキューされた3つのメッセージを異なる順序で返すクライアント参照の2つのセットを示します。クライアントがメッセージの決定的な順序付けを必要とする場合は、このクライアントに対して障害が発生します。たとえば、クライアントが参照を実行してプログラム状態を開始すると、後続のデキューによって予想と異なる順序でメッセージが返される場合があります。

8.3.2 コミット時間キューの仕組み

キューにエンキューされたメッセージのコミット・システム変更番号(CSCN)は、メッセージを含むトランザクションのコミットに関するREDOレコードがOracle DatabaseでREDOログに書き込まれるまで不明です。メッセージのエンキュー時にCSCNを記録することはできません。コミット時間キューでは、トランザクションのコミット時のデータベースの現行のSCNが、トランザクション内のすべてのメッセージに対する近似CSCNとして使用されます。コミット時間キュー内のメッセージの順序は、メッセージをエンキューしたトランザクションの近似CSCNに基づきます。

コミット時間キューでは、近似CSCNを使用してメッセージの決定的な順序を確立できるまで、デキューおよび参照操作でトランザクション内のメッセージを参照することはできません。複数のトランザクションによって同じコミット時間キューにメッセージが同時にエンキューされる場合、複数のトランザクションがほぼ同時にコミットされたり、これらのトランザクションのコミット間隔が重複する可能性があります。この場合、これらのトランザクション内のメッセージは、トランザクションがコミットされるまで参照できません。その時点では、メッセージの順序は各トランザクションの近似CSCNを使用して決定できます。エンキュー時間ではなくメッセージの近似CSCNを使用することによって、依存性が保持されます。順序が完全に決定されたメッセージのみを参照可能にすることによって、参照の読取りの一貫性が保持されます。

コミット時間キューは、常に、データベース・トランザクションに基づくメッセージに対してトランザクション間の依存性による順序付けを保持します。ただし、アプリケーションおよびユーザーが、データベース・トランザクションに基づかないメッセージをエンキューする場合があります。これらのメッセージでは、トランザクション間に依存性が存在する場合には、アプリケーションまたはユーザーは、トランザクションが正しい順序でコミットされること、および依存するトランザクションのコミット間隔が重複しないことを保証する必要があります。

コミット時間キューによって記録されたトランザクションの近似CSCNには、これらのトランザクションの実際のコミット順序が反映されない場合があります。たとえば、トランザクション1およびトランザクション2は、メッセージのエンキュー後、ほぼ同時にコミットされる可能性があります。トランザクション1の近似CSCNがトランザクション2の近似CSCNより小さい場合に、トランザクション2よりもトランザクション1の方がコミットの完了に時間がかかる場合があります。この場合、トランザクション2の実際のCSCNは、トランザクション1の実際のCSCNより小さくなります。

注意:

CREATE_QUEUE_TABLEsort_listパラメータを次のように設定できます。

priority, commit_time

この場合、まず優先順位によって、次にコミット時間によって順序付けが行われます。そのため、この設定は、優先順位の異なるメッセージに対して、トランザクション間の依存性による順序付けおよび参照の読取り一貫性を保証しません。ただし、優先順位が同じメッセージに対しては、トランザクション間の依存性による順序付けと参照の読取り一貫性が保証されます。

関連項目:

コミット時間キューの作成の詳細は、『Oracle Streamsレプリケーション管理者ガイド』を参照