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クライアントに関連付けることができます。たとえば、適用プロセスに適用ユーザーとしてhr
とoe
の両方を含めることはできませんが、hr
を複数の適用プロセスの適用ユーザーにすることはできます。
取得プロセス、同期取得、適用プロセスまたはメッセージ・クライアントを削除しても、これらのOracle Streamsクライアントの保護キュー・ユーザーとして構成されていたユーザーは、引き続きキューの保護キュー・ユーザーのままです。保護キュー・ユーザーとしてのユーザーを削除するには、ユーザーごとにDBMS_AQADM
パッケージのDISABLE_DB_ACCESS
プロシージャを実行します。また、不要になったエージェントは削除できます。
注意:
伝播および保護キューについては構成は必要ありません。つまり、伝播の削除時に、伝播のキューから保護キュー・ユーザーを削除するための追加の手順は必要ありません。
関連項目:
-
Oracle Streams AQエージェントと
DBMS_AQADM
パッケージの使用方法の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照
8.2 トランザクション・キューと非トランザクション・キュー
トランザクション・キューは、複数のメッセージを1つのトランザクションとして適用されるセットにグループ化できるキューです。つまり、適用プロセスでは、グループ内のすべてのメッセージを適用した後にCOMMIT
を実行します。非トランザクション・キューは、各メッセージが個別のトランザクションであるキューです。つまり、適用プロセスは、各メッセージが適用された後に、COMMIT
を実行します。どちらの場合も、メッセージはLCRまたはユーザー・メッセージのいずれかです。
DBMS_STREAMS_ADM
パッケージのSET_UP_QUEUE
プロシージャでは、常にトランザクション・キューが作成されます。トランザクション・キューと非トランザクション・キューの違いが重要になるのは、アプリケーション、同期取得または適用プロセスによってエンキューされたメッセージに対してのみです。適用プロセスは、常にソース・データベースで実行されたトランザクションが保つトランザクション内で取得LCRを適用します。
表8-1に、メッセージ・タイプとキューの型ごとに、適用プロセスの動作を示します。
表8-1 トランザクション・キューと非トランザクション・キューに対する適用プロセスの動作
メッセージ・タイプ | トランザクション・キュー | 非トランザクション・キュー |
---|---|---|
取得LCR |
適用プロセスは元のトランザクションを保持します。 |
適用プロセスは元のトランザクションを保持します。 |
永続LCRまたは永続ユーザー・メッセージ |
ユーザーが指定したメッセージのグループを、1つのトランザクションとして適用します。 |
各メッセージをそれぞれのトランザクション内で適用します。 |
ソース・データベースで実行されたトランザクションを保持する必要がある場合は、トランザクション・キューを使用してメッセージを格納します。同期取得で取得されたLCRがトランザクション・キューに格納されていることを確認します。
関連項目:
-
「キューの管理」
-
メッセージのグループ化の詳細は、『Oracle Databaseアドバンスト・キューイング・ユーザーズ・ガイド』を参照
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
の他に、priority
とenq_time
を設定できます。priority
を設定すると、エンキュー時に指定された優先順位の高いものから順にメッセージが順序付けされます。enq_time
を設定すると、エンキューされた時間の古いものから順にメッセージが順序付けされます。
コミット時間キューは、環境でメッセージの同時エンキューに対して次のいずれかの要件をサポートする必要がある場合に役立ちます。
コミット時間キューでは、これらの要件がサポートされます。優先順位またはエンキュー時間による順序付けでは、トランザクション間の依存性の違反および一貫性のない参照が許可されるため、いずれの順序付けでもこれらの要件はサポートされません。これらの設定では、元の依存性にかかわらずメッセージがデキューされるため、トランザクションの間の依存性の違反が許可されます。また、これらの設定では、デキュー操作を伴わずに実行される複数の参照によってメッセージの様々なセットが生成されるため、キュー内のメッセージの一貫性のない参照が許可されます。
関連項目:
8.3.1.1 デキュー時のトランザクション間の依存性による順序付け
1つのデータベース・トランザクションを正常にコミットするために別のデータベース・トランザクションのコミットを必要とする場合、トランザクション間の依存性が発生します。データベース・トランザクションに関する情報を含むメッセージをエンキューできます。たとえば、データベース・トリガーによってメッセージのエンキューを実行できます。図8-1に、エンキュー時間による順序付けで、これらのメッセージのデキュー時にトランザクション間の依存性による順序付けがサポートされないことを示します。
図8-1に、エンキュー時間による順序付けで、トランザクション間の依存性による順序付けが違反される場合があることを示します。メッセージe2
をエンキューしたトランザクションは、メッセージe1
およびe3
をエンキューしたトランザクションがコミットされる前にコミットされています。メッセージe3
に含まれる更新は、メッセージe2
に含まれる挿入に依存しています。そのため、トランザクション間の依存性をサポートする正しいデキュー順序は、e2
、e1
、e3
になります。ただし、エンキュー時間による順序付けでは、e2
の前にe3
をデキューできます。そのため、e3
のデキュー時に、e3
に含まれる変更をアプリケーションがhr.employees
表に適用しようとすると、エラーが発生します。また、3つのメッセージがすべてデキューされた後、e3
に含まれる変更が実行されていないために、hr.employees
表の行に誤った情報が含まれています。
8.3.1.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_TABLE
のsort_list
パラメータを次のように設定できます。
priority, commit_time
この場合、まず優先順位によって、次にコミット時間によって順序付けが行われます。そのため、この設定は、優先順位の異なるメッセージに対して、トランザクション間の依存性による順序付けおよび参照の読取り一貫性を保証しません。ただし、優先順位が同じメッセージに対しては、トランザクション間の依存性による順序付けと参照の読取り一貫性が保証されます。
関連項目:
コミット時間キューの作成の詳細は、『Oracle Streamsレプリケーション管理者ガイド』を参照