10 XStream Inの管理
XStream In構成を管理できます。
この章では、インバウンド・サーバーでのルール、ルール・セットまたはルールベースの変換の使用については扱いません。デフォルトでは、インバウンド・サーバーはルールまたはルール・セットを使用しません。したがって、インバウンド・サーバーは、XStreamクライアント・アプリケーションにより送信された論理変更レコード(LCR)をすべて適用します。ただし、インバウンド・サーバーに送信されたLCRをフィルタリングするために、DBMS_XSTREAM_ADM
パッケージとDBMS_RULE_ADM
パッケージを使用して、ルールおよびルール・セットをインバウンド・サーバーに追加できます。DBMS_XSTREAM_ADM
パッケージを使用してルールベースの変換を指定することもできます。
関連項目:
ルール、ルール・セットおよびルールベースの変換の使用の詳細は、Oracle Streams概要および管理を参照してください
10.1 XStream Inの管理について
XStream In構成の一部であるインバウンド・サーバーなどのデータベース・コンポーネントを変更できます。
XStream Inデータベース・コンポーネントを管理するためのメイン・インタフェースはPL/SQLです。具体的には、オラクル社が提供する次のPL/SQLパッケージを使用してXStream Inを管理します。
-
DBMS_XSTREAM_ADM
DBMS_XSTREAM_ADM
パッケージは、XStream Inを管理するためのメイン・パッケージです。このパッケージには、インバウンド・サーバーを構成、変更または削除するためのサブプログラムが含まれています。また、このパッケージによって、インバウンド・サーバーで使用されるルール、ルール・セットおよびルールベースの変換を変更できます。関連項目:
このパッケージの詳細は、Oracle Database PL/SQLパッケージおよびタイプ・リファレンスを参照
-
DBMS_XSTREAM_AUTH
DBMS_XSTREAM_AUTH
パッケージでは、XStream管理者を構成および変更できます。関連項目:
-
このパッケージを使用してXStream管理者を作成する方法については、XStream管理者の構成を参照
-
このパッケージの詳細は、Oracle Database PL/SQLパッケージおよびタイプ・リファレンスを参照
-
-
DBMS_APPLY_ADM
DBMS_APPLY_ADM
パッケージでは、インバウンド・サーバーを変更できます。関連項目:
このパッケージの詳細は、Oracle Database PL/SQLパッケージおよびタイプ・リファレンスを参照
10.2 インバウンド・サーバーの起動
XStreamクライアント・アプリケーションから論理変更レコード(LCR)を受信し、LCRを適用するには、インバウンド・サーバーを有効にする必要があります。既存のインバウンド・サーバーを起動するには、DBMS_APPLY_ADM
パッケージのSTART_APPLY
プロシージャを実行します。
インバウンド・サーバーを起動するには、次のようにします。
-
インバウンド・サーバー・データベースにXStream管理者として接続します。
SQL*Plusでのデータベースへの接続の詳細は、Oracle Database管理者ガイドを参照してください。
-
DBMS_APPLY_ADM
パッケージのSTART_APPLY
プロシージャを実行して、apply_name
パラメータにインバウンド・サーバーを指定します。
次の例では、xin
という名前のインバウンド・サーバーが起動します。
例10-1 xoutという名前のインバウンド・サーバーの起動
BEGIN DBMS_APPLY_ADM.START_APPLY( apply_name => 'xin'); END; /
関連項目:
Oracle Enterprise Manager Cloud Controlを使用して適用プロセスまたはインバウンド・サーバーを起動する手順については、Oracle Enterprise Manager Cloud Controlのオンライン・ヘルプを参照
10.3 インバウンド・サーバーの停止
既存のインバウンド・サーバーを停止するには、DBMS_APPLY_ADM
パッケージのSTOP_APPLY
プロシージャを実行します。XStream構成内の問題のトラブルシューティングを行う際に、インバウンド・サーバーを停止することがあります。
インバウンド・サーバーを停止するには、次のようにします。
-
インバウンド・サーバー・データベースにXStream管理者として接続します。
SQL*Plusでのデータベースへの接続の詳細は、Oracle Database管理者ガイドを参照してください。
-
DBMS_APPLY_ADM
パッケージのSTOP_APPLY
プロシージャを実行して、apply_name
パラメータにインバウンド・サーバーを指定します。
次の例では、xin
という名前のインバウンド・サーバーが停止します。
例10-2 xoutという名前のインバウンド・サーバーの停止
BEGIN DBMS_APPLY_ADM.STOP_APPLY( apply_name => 'xin'); END; /
関連項目:
Oracle Enterprise Manager Cloud Controlを使用して適用プロセスまたはインバウンド・サーバーを停止する手順については、Oracle Enterprise Manager Cloud Controlのオンライン・ヘルプを参照
10.4 インバウンド・サーバーの適用パラメータの設定
適用パラメータによって、インバウンド・サーバーの動作方法を制御します。インバウンド・サーバーの適用パラメータを設定するには、DBMS_XSTREAM_ADM
パッケージのSET_PARAMETER
プロシージャを使用します。
インバウンド・サーバーの適用パラメータを設定するには、次のようにします。
-
アウトバウンド・サーバー・データベースにXStream管理者として接続します。
SQL*Plusでのデータベースへの接続の詳細は、Oracle Database管理者ガイドを参照してください。
-
DBMS_XSTREAM_ADM
パッケージのSET_PARAMETER
プロシージャを実行して、次のパラメータを指定します。-
streams_name
: インバウンド・サーバーの名前を指定します。 -
streams_type
:apply
を指定します。 -
parameter
: 適用パラメータの名前を指定します。 -
value
: 適用パラメータの値を指定します。
-
次の例では、xin
という名前のインバウンド・サーバーのparallelism
パラメータが4
に設定されます。
例10-3 インバウンド・サーバー・パラメータの設定
BEGIN DBMS_XSTREAM_ADM.SET_PARAMETER( streams_name => 'xin', streams_type => 'apply', parameter => 'parallelism', value => '4'); END; /
注意:
-
value
パラメータは、パラメータ値が数値の場合にも、常にVARCHAR2
値として入力されます。 -
value
パラメータがNULL
に設定されているか、または指定されていない場合、パラメータはデフォルト値に設定されます。
関連項目:
-
Oracle Enterprise Manager Cloud Controlを使用して適用パラメータを設定する手順については、Oracle Enterprise Manager Cloud Controlのオンライン・ヘルプを参照
-
適用パラメータの詳細は、Oracle Database PL/SQLパッケージおよびタイプ・リファレンスを参照
10.5 インバウンド・サーバーの適用ユーザーの変更
インバウンド・サーバーではその適用ユーザーのセキュリティ・ドメイン内にLCRが適用され、クライアント・アプリケーションは適用ユーザーとしてインバウンド・サーバーに連結する必要があります。DBMS_XSTREAM_ADM
パッケージのALTER_INBOUND
プロシージャを使用して、インバウンド・サーバーの適用ユーザーを変更できます。
クライアント・アプリケーションがインバウンド・サーバーに異なるユーザーとして接続する必要がある場合、または異なるユーザーに関連付けられている権限を使用して変更を適用する場合に、適用ユーザーを変更できます。適用ユーザーに必須権限が付与されていることを確認してください。
関連項目:
適用ユーザーに必要な権限の詳細は、Oracle Database PL/SQLパッケージおよびタイプ・リファレンスを参照
インバウンド・サーバーの適用ユーザーを変更するには、次のようにします。
-
インバウンド・サーバー・データベースにXStream管理者として接続します。
XStream管理者は、インバウンド・サーバーの適用ユーザーを変更するには
DBA
ロールが付与されている必要があります。SQL*Plusでのデータベースへの接続の詳細は、Oracle Database管理者ガイドを参照してください。
-
DBMS_XSTREAM_ADM
パッケージのALTER_INBOUND
プロシージャを実行して、次のパラメータを指定します。-
server_name
- インバウンド・サーバーの名前を指定します。 -
apply_user
- 新しい適用ユーザーを指定します。
-
例10-4 インバウンド・サーバーの適用ユーザーの変更
xin
という名前のインバウンド・サーバーの適用ユーザーをhr
に変更するには、次のプロシージャを実行します。
BEGIN DBMS_XSTREAM_ADM.ALTER_INBOUND( server_name => 'xin', apply_user => 'hr'); END; /
10.6 XStream Inの競合の検出および解消の管理
複数のクライアントが同じ表の行をほぼ同時に変更すると、競合が発生する可能性があります。XStream Inは競合を検出し、競合を解消するための方法を提供します。
10.6.1 XStream環境内のDMLの競合
競合とは、LCR内の古い値と、表内のデータが一致しないことです。
複数データベース上で同じデータに対して同時のデータ操作言語(DML)操作を許可しているXStream環境では、競合が発生する可能性があります。XStream環境でDMLの競合が発生する可能性があるのは、インバウンド・サーバーがDML操作によって生じる行の変更を含む行LCRを適用している場合のみです。インバウンド・サーバーは、行LCRで発生した競合を自動的に検出します。
たとえば、異なるデータベースで発生した2つのトランザクションによって同じ行がほぼ同時に更新されると、競合が発生する場合があります。XStream環境の構成時には、競合の発生を許可するかどうかを考慮する必要があります。システム設計で競合が許可されている場合は、競合を自動的に解消するように競合解消を構成できます。
一般的なベスト・プラクティスは、起こりうる競合を防止するXStream環境を設計することです。この章で後述する競合防止技法を使用すると、ほとんどのシステム設計で共有データ全体または大部分における競合を防止できます。ただし、多くのアプリケーションでは、複数のデータベースで共有データをある程度の割合まで随時更新可能にする必要があります。この場合は、競合の可能性への対処が必要となります。
注意:
インバウンド・サーバーではDDLの競合が検出されません。この種の競合が環境で防止されることを確認してください。
関連トピック
10.6.2 XStream環境内の競合のタイプ
複数のデータベースでデータを共有する場合は、いくつかの異なるタイプの競合が発生する可能性があります。
10.6.2.1 XStream環境内の更新の競合
更新の競合が発生するのは、インバウンド・サーバーで適用される行LCRに含まれている行の更新が、同じ行の他の更新と競合する場合です。
また、異なるデータベースからの2つのトランザクションによって、同じ行がほぼ同時に更新される場合にも、更新の競合が発生する可能性があります。
10.6.2.2 XStream環境内の一意性競合
一意性競合が発生するのは、インバウンド・サーバーで適用される行LCRに含まれている行の変更が、PRIMARY
KEY
制約やUNIQUE
制約など、一意性の整合性制約に違反している場合です。
たとえば、2つの異なるデータベースからの2つのトランザクションがあり、それぞれのトランザクションが同じ主キー値を持つ表に1行を挿入する場合を考えます。この場合は、これらのトランザクションによって一意性競合が発生します。
10.6.2.3 XStream環境内の削除の競合
削除の競合 が発生するのは、異なるデータベースで発生した2つのトランザクションがあり、1つのトランザクションで1行を削除し、もう1つのトランザクションで同じ行を更新または削除する場合です。
この場合、行LCR内で参照される行は存在しないため、更新または削除できません。
10.6.2.4 XStream環境内の外部キーの競合
外部キーの競合が発生するのは、インバウンド・サーバーで適用される行LCRに含まれている行の変更が、外部キー制約に違反している場合です。
たとえば、hr
スキーマ内で、employees
表のdepartment_id
列は、departments
表のdepartment_id
列の外部キーです。次の変更が2つの異なるデータベース(A
とB
)で発生し、3つ目のデータベース(C
)に伝播される場合を考えます。
-
データベース
A
で、department_id
が271
の1行がdepartments
表に挿入されます。この変更はデータベースB
に伝播され、そこで適用されます。 -
データベース
B
で、employee_id
が206
、department_id
が271
の1行がemployees
表に挿入されます。
データベースB
で発生した変更がデータベースA
で発生した変更よりも先にデータベースC
で適用されると、データベースC
のdepartments
表にはまだdepartment_id
が271
の部門の行が存在しないため、外部キーの競合が発生します。
10.6.3 XStream環境内の競合とトランザクションの順序付け
XStream環境では、3つ以上のデータベースがデータを共有し、そのうち2つ以上のデータベースでデータが更新されると、順序付けの競合が発生する可能性があります。
たとえば、3つのデータベースがhr.departments
表の情報を共有している使用例を考えます。データベースの名前はmult1.example.com
、mult2.example.com
およびmult3.example.com
です。mult1.example.com
でhr.departments
表の1行が変更され、その変更がmult2.example.com
とmult3.example.com
の両方に伝播されると想定します。次の一連のアクションが発生する可能性があります。
-
変更が
mult2.example.com
に伝播します。 -
mult2.example.com
のインバウンド・サーバーは、mult1.example.com
からの変更を適用します。 -
mult2.example.com
で、同じ行に対して別の変更が行われます。 -
mult2.example.com
での変更がmult3.example.com
に伝播します。 -
mult3.example.com
のインバウンド・サーバーは、mult3.example.com
の別のインバウンド・サーバーがmult1.example.com
からの変更を適用する前に、mult2.example.com
からの変更を適用しようとします。
この場合、mult3.example.com
での行の列値はmult2.example.com
から伝播した行LCR内の対応する元の値と一致しないため、競合が発生します。
トランザクションが順不同で適用されると、データ競合の原因となるのみでなく、データのサポートがリモート・データベースに正常に伝播されていないと、そのデータベースで参照整合性の問題が発生する場合があります。新規の顧客が受注部門に連絡する場合の使用例を考えます。顧客レコードが作成され、受注が処理されます。リモート・データベースで受注データが顧客データより前に適用されると、受注で参照されている顧客はリモート・データベースに存在しないため、参照整合性エラーが発生します。
順序付けの競合が発生した場合は、必要なデータがリモート・データベースに伝播して適用されてから、エラー・キューにあるトランザクションを再実行すれば、競合を解消できます。
10.6.4 XStream環境内の競合検出
インバウンド・サーバーは自動的に競合を検出します。
10.6.4.1 XStream環境内の競合検出について
インバウンド・サーバーは、更新、一意性、削除および外部キーの競合を検出します。
インバウンド・サーバーは、これらの競合を次のように検出します。
-
行LCR内の行の元の値と、宛先データベースにある同じ行の現行の値が一致しない場合は、インバウンド・サーバーによって更新の競合が検出されます。
-
挿入または更新操作を含むLCRの適用時に一意制約違反が発生すると、インバウンド・サーバーによって一意性競合が検出されます。
-
更新または削除操作を含むLCRの適用時に、行の主キーが存在しないためにその行が見つからないと、インバウンド・サーバーによって削除の競合が検出されます。
-
LCRの適用時に外部キー制約違反が発生すると、インバウンド・サーバーによって外部キーの競合が検出されます。
競合は、インバウンド・サーバーがLCRを直接適用しようとしたとき、またはDML競合ハンドラなどのインバウンド・サーバー・ハンドラがLCRに対してEXECUTE
メンバー・プロシージャを実行したときに検出される場合があります。また、DBMS_APPLY_ADM
パッケージのEXECUTE_ERROR
またはEXECUTE_ALL_ERRORS
プロシージャの実行時にも、競合が検出される場合があります。
注意:
-
列を更新して、この列の古い値と新しい値が等しい場合、Oracle Databaseではこの列の更新で競合は検出されません。
-
更新LCR、削除LCRおよびLOB列に対するピース単位更新を取り扱うLCR内の古いLOB値は、競合検出には使用されません。
10.6.5 XStream環境内の競合防止
データの競合を防止するためのいくつかの方法があります。
10.6.5.1 プライマリ・データベース所有権モデルの使用
共有データを含む表への同時更新アクセスを行うデータベースの数を制限することによって、競合の可能性を回避できます。
プライマリ所有権を使用すると、共有データ・セットへの更新が1つのデータベースにしか許可されないため、すべての競合が防止されます。アプリケーションでは、行と列のサブセットを使用して、データの所有権を表レベルよりも細かく設定できます。たとえば、アプリケーションでは、共有表の特定の列や行への更新アクセス権を、データベースごとに設定できます。
10.6.5.2 特定タイプの競合の防止
プライマリ・データベース所有権モデルではアプリケーション要件にとって限定的すぎる場合は、共有所有権データ・モデルを使用できますが、これは、競合が発生する可能性があることを意味します。その場合でも、通常は、特定のタイプの競合を回避するためにいくつかの簡単な方法を使用する必要があります。
10.6.5.2.1 XStream環境内の一意性競合の防止
各データベースで共有データに一意識別子を使用させることで、一意性競合を回避できます。
XStream環境ですべてのデータベースに一意識別子を確実に使用させるには、3つの方法があります。
-
その1つは、次のSELECT文を実行して一意識別子を構成することです。
SELECT SYS_GUID() OID FROM DUAL;
このSQL演算子は、16バイトのグローバル一意識別子を戻します。グローバルに一意な識別子は、次の形式で表示されます。
A741C791252B3EA0E034080020AE3E0A
-
また、データを共有する各データベースで順序を作成し、データベース名(または他のグローバル一意値)をローカルの順序と連結して一意性競合を防止する方法もあります。このアプローチを使用すると、重複する順序値を回避し、一意性競合を防止できます。
-
最後に、2つのデータベースで同じ値を生成できないように、データを共有する各データベースでカスタマイズされた順序を作成する方法があります。これを実現するには、
CREATE
SEQUENCE
文で開始値、増分値および最大値の組合せを使用します。たとえば、次の順序を構成できます。表10-1 カスタマイズされた順序
パラメータ データベースA データベースB データベースC START
WITH
1
3
5
INCREMENT
BY
10
10
10
範囲の例
1, 11, 21, 31, 41,...
3, 13, 23, 33, 43,...
5, 15, 25, 35, 45,...
同様のアプローチを使用すると、データベースごとに一意の範囲を生成する
START
WITH
およびMAXVALUE
を指定して、各データベースに異なる範囲を定義できます。
10.6.6 XStream環境内の競合解消
更新の競合が検出された場合、競合ハンドラではその解消を試みることができます。
10.6.6.1 XStream環境内の競合解消について
XStreamには、挿入および更新の競合を解消するためのビルトインの競合ハンドラが用意されています。
削除、外部キーまたは順序付けの競合には、ビルトインの競合ハンドラはありません。ただし、ビジネス・ルールに固有のデータ競合を解消するために、独自のカスタム競合ハンドラを作成できます。この種の競合ハンドラは、プロシージャDMLハンドラまたはエラー・ハンドラに付属させることができます。
ビルトイン競合ハンドラとカスタム競合ハンドラのどちらを使用する場合も、競合が検出されるとただちに使用されます。指定した競合ハンドラでも関連する適用ハンドラでも競合を解消できない場合、その競合はエラー・キューに記録されます。競合が発生した場合は、関連する適用ハンドラを使用してデータベース管理者に通知する必要があります。
競合のためにトランザクションがエラー・キューに移動される場合は、競合の原因となった条件を訂正できる場合があります。このような場合は、DBMS_APPLY_ADM
パッケージのEXECUTE_ERROR
プロシージャを使用してトランザクションを再実行できます。
関連項目:
DBMS_APPLY_ADM
パッケージのEXECUTE_ERROR
プロシージャの詳細は、Oracle Database PL/SQLパッケージおよびタイプ・リファレンスを参照
10.6.6.2 ビルトインのDML競合ハンドラ
使用できるビルトインのDML競合ハンドラにはいくつかのタイプがあります。列リストおよび解消列はビルトインのDML競合ハンドラで使用されます。
列リストは、挿入または更新の競合がある場合にDML競合ハンドラがコールされる列のリストです。解消列は、DML競合ハンドラを識別します。ビルトインのDML競合ハンドラMAXIMUM
またはMINIMUM
を使用する場合は、解消列も競合の解消に使用されます。解消列は、ハンドラの列リスト内の列の1つである必要があります。
特定の表について1つ以上のDML競合ハンドラを指定するには、DBMS_APPLY_ADM
パッケージのSET_DML_CONFLICT_HANDLER
プロシージャを使用します。削除または外部キーの競合には、ビルトインのDML競合ハンドラはありません。
関連項目:
-
DML競合ハンドラを設定および削除する方法については、DML競合ハンドラの管理を参照
-
SET_DML_CONFLICT_HANDLER
プロシージャの詳細は、Oracle Database PL/SQLパッケージおよびタイプ・リファレンスを参照
10.6.6.3 ビルトインのDML競合ハンドラのタイプ
Oracleには、Oracle Streams環境用にRECORD
、IGNORE
、OVERWRITE
、MAXIMUM
、MINIMUM
およびDELTA
タイプのビルトインのDML競合ハンドラが用意されています。
このトピックで後述する各タイプのハンドラの説明では、次の競合例について取り上げます。
-
dbs1.example.com
ソース・データベースで次の更新が行われます。UPDATE hr.employees SET salary = 4900 WHERE employee_id = 200; COMMIT;
この更新によって、従業員
200
の給与が4400
から4900
に変更されます。 -
ほぼ同時に、
dbs2.example.com
宛先データベースで次の更新が行われます。UPDATE hr.employees SET salary = 5000 WHERE employee_id = 200; COMMIT;
-
取得プロセスは、
dbs1.example.com
ソース・データベースで更新を取得し、結果の行LCRをキューに入れます。 -
伝播は
dbs1.example.com
のキューからdbs2.example.com
のキューに行LCRを伝播させます。 -
dbs2.example.com
の適用プロセスは、行LCRをhr.employees
表に適用しようとしますが、dbs2.example.com
の給与値は5000
であり、これは行LCR内の給与の元の値(4400
)と一致しないため、競合が発生します。
ここでは、各ビルトイン競合ハンドラと、それぞれがこの競合をどのように解消するかについて説明します。
RECORD
競合が発生した場合、RECORD
ハンドラはLCRをエラー・キューに配置します。RECORD
ハンドラはすべての競合タイプに使用できますが、表内のすべての列を含む列グループに対してのみ指定できます。
RECORD
ハンドラを競合例のdbs2.example.com
宛先データベースのhr.employees
表に使用すると、dbs1.example.com
の行LCRはdbs1.example.com
のエラー・キューに配置され、その変更は適用されません。したがって、競合解消後は、dbs2.example.com
での従業員200
の給与は5000
となります。
IGNORE
競合が発生すると、IGNORE
ハンドラはソース・データベースからのLCR内の値を無視し、宛先データベースの値を保持します。
IGNORE
ハンドラを競合例のdbs2.example.com
宛先データベースのhr.employees
表に使用すると、行LCR内の新規の値が廃棄されます。したがって、競合解消後は、dbs2.example.com
での従業員200
の給与は5000
となります。
OVERWRITE
競合が発生すると、OVERWRITE
ハンドラは、宛先データベースの現行の値をソース・データベースからのLCR内の新規の値で置換します。
OVERWRITE
ハンドラを競合例のdbs2.example.com
宛先データベースのhr.employees
表に使用すると、行LCR内の新規の値によってdbs2.example.com
の値が上書きされます。したがって、競合解消後は、従業員200
の給与は4900
となります。
MAXIMUM
競合が発生すると、MAXIMUM
競合ハンドラは、指定された解消列について、ソース・データベースからのLCRにある新規の値を、宛先データベース内の現行の値と比較します。LCRにある解消列の新規の値が宛先データベースの列の現行値より大きければ、適用プロセスではLCRを使用して競合が解消されます。LCRにある解消列の新規の値が宛先データベースの列の現行値より小さければ、適用プロセスでは宛先データベースを使用して競合が解消されます。
MAXIMUM
ハンドラを競合例のdbs2.example.com
宛先データベースにあるhr.employees
表のsalary
列に使用すると、行LCRにある給与は表にある現行の給与より小さいため、適用プロセスでは行LCRは適用されません。したがって、競合解消後は、dbs2.example.com
での従業員200
の給与は5000
となります。
関係するトランザクションの時間ベースで競合を解消する場合は、トリガーを使用してトランザクションの時刻が自動的に記録されるように、共有表に列を追加する方法があります。この場合は、この列をMAXIMUM
競合ハンドラ用の解消列として指定でき、最新(または最大)時刻を伴うトランザクションが自動的に使用されます。
ここでは、hr.employees
表に対するトランザクションの時刻を記録するトリガーの例を示します。job_id
、salary
およびcommission_pct
列は、競合解消ハンドラの列リストに含まれているとします。トリガーは、列リスト内の列に対してUPDATE
が実行されるか、INSERT
が実行された場合にのみ起動します。
ALTER TABLE hr.employees ADD (time TIMESTAMP WITH TIME ZONE); CREATE OR REPLACE TRIGGER hr.insert_time_employees BEFORE INSERT OR UPDATE OF job_id, salary, commission_pct ON hr.employees FOR EACH ROW BEGIN -- Consider time synchronization problems. The previous update to this -- row might have originated from a site with a clock time ahead of the -- local clock time. IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN :NEW.TIME := SYSTIMESTAMP; ELSE :NEW.TIME := :OLD.TIME + 1 / 86400; END IF; END; /
この種のトリガーを競合解消に使用する場合は、トリガーの起動プロパティがデフォルトの「1回起動」に設定されていることを確認してください。設定が異なると、適用プロセスによってトランザクションが適用されるときに新規時刻がマークされ、トランザクションの実際時刻が失われる可能性があります。
MINIMUM
競合が発生すると、MINIMUM
競合ハンドラは、指定された解消列について、ソース・データベースからのLCRにある新規の値を、宛先データベース内の現行の値と比較します。LCRにある解消列の新規の値が宛先データベースの列の現行値より小さければ、適用プロセスではLCRを使用して競合が解消されます。LCRにある解消列の新規の値が宛先データベースの列の現行値より大きければ、適用プロセスでは宛先データベースを使用して競合が解消されます。
MINIMUM
ハンドラを競合例のdbs2.example.com
宛先データベースにあるhr.employees
表のsalary
列に使用すると、行LCRにある給与は表にある現行の給与より小さいため、適用プロセスでは行LCRを使用して競合が解消されます。したがって、競合解消後は、従業員200
の給与は4900
となります。
DELTA
競合が発生すると、DELTA
競合ハンドラは、列の古い値と新しい値の差を計算し、この差を列の現在の値に加算します。DELTA
競合ハンドラは、conflict_type
がROW_EXISTS
に設定され、列グループ内のすべての列が数値の場合にのみ使用できます。
DELTA
ハンドラを競合例のdbs2.example.com
宛先データベースにあるhr.employees
表のsalary
列に使用すると、適用プロセスでは、列の古い値と新しい値の差を計算し(4900 – 4400 = 500)、列の現在の値に差を加算する(5000 + 500 = 5500)ことによって競合が解消されます。したがって、競合解消後は、従業員200
の給与は5500
となります。
MAX_AND_EQUALS
競合が発生したとき、解消列の値がデータベース内の列の値以上である場合にLCRからの列リストを適用します。それ以外の場合は、LCRは破棄されます。
MAX_AND_EQUALS
ハンドラを競合例のdbs2.example.com
宛先データベースのhr.employees
表のsalary
列に使用すると、適用プロセスではLCRを破棄することによって競合が解消されます。したがって、競合解消後は、従業員200
の給与は5000
となります。
MIN_AND_EQUALS
競合が発生したとき、解消列の値がデータベース内の列の値以下である場合にLCRからの列リストを適用します。それ以外の場合は、LCRは破棄されます。
MIN_AND_EQUALS
ハンドラを競合例のdbs2.example.com
宛先データベースのhr.employees
表のsalary
列に使用すると、適用プロセスではLCRを適用することによって競合が解消されます。したがって、競合解消後は、従業員200
の給与は4900
となります。
10.6.6.4 列リスト
表に対してビルトインのDML競合ハンドラを指定するたびに、列リストを指定する必要があります。
列リストは、DML競合ハンドラがコールされる列のリストです。インバウンド・サーバーが行LCRを適用するときに、リスト内の1つ以上の列に更新の競合が発生すると、競合を解消するためにDML競合ハンドラがコールされます。リストにない列にのみ競合が発生した場合、DML競合ハンドラはコールされません。競合解消の有効範囲は、1つの行LCRの1つの列リストです。
特定の表に対してDML競合ハンドラを複数指定することはできますが、同じ列を複数の列リストに含めることはできません。たとえば、hr.employees
表にビルトインのDML競合ハンドラを2つ指定する場合を考えます。
-
最初のDML競合ハンドラの列リストには、列
salary
およびcommission_pct
を指定します。 -
2番目のDML競合ハンドラの列リストには、列
job_id
およびdepartment_id
を指定します。
また、この表に他の競合ハンドラは存在しないものと想定します。この場合、次の例は様々なシナリオの結果を示しています。
-
インバウンド・サーバーが行LCRを適用するときに
salary
列に競合が発生すると、競合を解消するために最初のDML競合ハンドラがコールされます。 -
department_id
列に競合が発生すると、競合を解消するために2番目のDML競合ハンドラがコールされます。 -
どの競合ハンドラの列リストにもない列に競合が発生すると、競合ハンドラはコールされず、エラーになります。たとえば、
hr.employees
表のmanager_id
列に競合が発生すると、エラーになります。 -
行LCRの適用時に複数の列リストに競合が発生し、列リストに属さない列での競合がなければ、競合が発生した列リストごとに適切なDML競合ハンドラが起動されます。
列リストを使用すると、データ型ごとに異なるハンドラを使用して競合を解消できます。たとえば、通常、数値データにはMAXIMUMまたはMINIMUM競合ハンドラが適しており、文字データにはOVERWRITEまたはDISCARD競合ハンドラが適しています。
列リストにない列に競合が発生すると、表に対する特定の操作用のエラー・ハンドラがそれを解消しようとします。エラー・ハンドラが競合を解消できない場合や、この種のエラー・ハンドラがない場合は、競合の原因となったトランザクションがエラー・キューに移動されます。
また、OVERWRITE
、MAXIMUM
またはMINIMUM
ビルトイン・ハンドラのいずれかを使用する列リスト内の列に競合が発生した場合に、この列リスト内のすべての列が行LCRに含まれていないと、使用可能でない値があるため、競合は解消できません。この場合は、競合の原因となったトランザクションがエラー・キューに移動されます。列リストでDISCARD
ビルトイン方法が使用されている場合は、行LCRにこの列リストのすべての列が含まれていない場合にも、行LCRが廃棄され、エラーは発生しません。
ソース・データベースの複数の列が宛先データベースの列リストに影響を与える場合、列リスト内で指定される列に対して条件付きのサプリメンタル・ログ・グループを指定する必要があります。サプリメンタル・ロギングをソース・データベースで指定し、競合を正しく解消するために必要な情報をLCRに追加します。通常、列リスト内の列に条件付きのサプリメンタル・ログ・グループを指定する必要があるのは、列リストに列が複数存在する場合であり、列リストに存在する列が1つのみの場合は指定する必要ありません。
ただし、列リストに存在する列が1つのみの場合でも、条件付きのサプリメンタル・ログ・グループが必要になることがあります。つまり、適用ハンドラまたはカスタム・ルールベースの変換で、ソース・データベースからの複数列を宛先データベースの列リストの単一行に結合する場合です。たとえば、カスタム・ルールベースの変換で、通り、州および郵便番号を格納するソース・データベースからの3行を使用し、そのデータを宛先データベースで単一の住所列に結合する場合です。
また、列リストに存在する列が複数の場合でも、条件付きのサプリメンタル・ログ・グループが不要なことがあります。たとえば、適用ハンドラまたはカスタム・ルールベースの変換で、ソース・データベースからの単一の住所列を宛先データベースの列リストの複数行に分割する場合です。カスタム・ルールベースの変換で、ソース・データベースの1つの住所列(通り、州および郵便番号を含む)を取得し、そのデータを宛先データベースの3列に分割する場合です。
注意:
ビルトインのDML競合ハンドラでは、LOB、LONG
、LONG
RAW
、ユーザー定義型およびOracleが提供する型の列はサポートされません。したがって、SET_DML_CONFLICT_HANDLER
プロシージャを実行するときには、column_list
パラメータにこれらの型の列を含めないでください。
関連項目:
10.6.6.5 解消列
解消列は、ビルトインのDML競合ハンドラの識別に使用される列です。
ビルトインのDML競合ハンドラMAXIMUM
またはMINIMUM
を使用する場合は、解消列も競合の解消に使用されます。解消列は、ハンドラの列リスト内の列の1つである必要があります。
たとえば、hr.employees
表のsalary
列をMAXIMUMまたはMINIMUM競合ハンドラの解消列として指定すると、行LCR内の列リストの値を適用するか、宛先データベースにおける列リストの値を保持するかを判断するためにsalary
列が評価されます。
競合に解消列が関係する次のどちらの状況でも、エラー・ハンドラで問題を解決できない場合は、適用プロセスは競合の原因となった行LCRを含むトランザクションをエラー・キューに移動します。これらの場合、競合は解消できず、宛先データベースの列の値がそのまま保持されます。
-
解消列について、新規のLCR値と宛先データベースの行の値が同一の場合(解消列が競合の原因となった列でない場合など)。
-
解消列の新規のLCR値、または宛先データベースの解消列の現行の値が
NULL
の場合。
注意:
解消列は、OVERWRITE
およびDISCARD
競合ハンドラには使用されませんが、解消列をこれらの競合ハンドラ用に指定する必要があります。
10.6.6.6 データ収束
複数のデータベース間でデータを共有しており、そのすべてでデータを同一にする必要がある場合は、すべてのデータベースでデータを収束させる競合解消ハンドラを使用してください。
すべてのデータベースで共有データの変更を許可する場合、表のデータ収束が可能になるのは、データを共有する全データベースが共有データに対する変更を取得し、データを共有する他のすべてのデータベースにその変更を伝播する場合のみです。
このような環境では、MAXIMUM
競合解消方法で収束を保証できるのは、解消列の値が常に増加する場合のみです。行の連続するタイム・スタンプがそれぞれ異なっている場合、時間ベースの解消列はこの要件を満たします。このような環境でMINIMUM
競合解消方法によって収束を保証できるのは、解消列の値が常に減少する場合のみです。
10.6.6.7 DML競合ハンドラを使用しない衝突処理
表のDML競合ハンドラがない場合、DBMS_APPLY_ADM
パッケージのHANDLE_COLLISIONS
プロシージャを使用して、基本的な衝突処理を有効にできます。
インバウンド・サーバーと表についての基本的な衝突処理を有効にする場合、競合は次の方法で解消されます。
-
表に存在する行について競合が検出された場合、行LCRのデータで表内のデータが上書きされます。
たとえば、行LCRに挿入が含まれているが、行がすでに表に存在するとします。行LCR内のデータで表内の既存のデータが上書きされます。行LCRに更新が含まれており、行の古い値が行LCRの古い値と一致しない場合、行LCRのデータで表内のデータが上書きされます。
-
表に存在しない行について競合が検出された場合、行LCRのデータは無視されます。
たとえば、行LCRに行の更新が含まれているが、行が表に存在しない場合、行LCRは無視されます。
例10-5 表の基本的な衝突処理の有効化
この例では、app_emp
インバウンド・サーバーおよびhr.employees
表の基本的な衝突処理が有効になります。BEGIN
DBMS_APPLY_ADM.HANDLE_COLLISIONS(
apply_name => 'app_emp',
enable => TRUE,
object => 'hr.employees');
END;
/
この表の基本的な衝突処理を無効にするには、同じプロシージャを実行しますが、enable
パラメータをFALSE
に設定します。
10.6.6.8 カスタム競合ハンドラ
PL/SQLプロシージャを作成し、カスタム競合ハンドラとして使用できます。
特定の表に1つ以上のカスタム競合ハンドラを指定するには、DBMS_APPLY_ADM
パッケージのSET_DML_HANDLER
プロシージャを使用します。特に、このプロシージャを実行してカスタム競合ハンドラを指定するときに、次のパラメータを設定します。
-
object_name
パラメータを、競合解消の対象となる表の完全修飾された名前に設定します。 -
object_type
パラメータをTABLE
に設定します。 -
operation_name
パラメータを、カスタム競合ハンドラのコール対象となる操作のタイプに設定します。可能な操作は、INSERT
、UPDATE
、DELETE
およびLOB_UPDATE
です。また、ハンドラをすべての操作のデフォルト・ハンドラとするために、operation_name
パラメータをDEFAULT
に設定できます。 -
エラー・ハンドラでエラー発生時に競合解消を実行する場合は、
error_handler
パラメータをTRUE
に設定します。また、競合解消をプロシージャDMLハンドラに組み込む場合は、error_handler
パラメータをFALSE
に設定します。このパラメータを
FALSE
に設定した場合は、LCR用のEXECUTE
メンバー・プロシージャを使用して行LCRを実行すると、指定したオブジェクトと操作に対してプロシージャDMLハンドラ内で競合解消が実行されます。 -
user_procedure
パラメータを設定して、競合解消用のプロシージャを指定します。このユーザー・プロシージャは、指定したタイプの操作によって指定した表に生じた競合を解消するためにコールされます。
カスタム競合ハンドラが競合を解消できない場合、インバウンド・サーバーは、競合を含むトランザクションをエラー・キューに移動し、そのトランザクションを適用しません。
特定のオブジェクトにビルトインのDML競合ハンドラとカスタム競合ハンドラの両方が存在する場合は、次の両方の条件が満たされる場合にのみビルトインのDML競合ハンドラが起動されます。
-
カスタム競合ハンドラで、LCR用の
EXECUTE
メンバー・プロシージャを使用して行LCRが実行される場合。 -
行LCR用の
EXECUTE
メンバー・プロシージャのconflict_resolution
パラメータがTRUE
に設定されている場合。
関連項目:
SET_DML_HANDLER
プロシージャの詳細は、Oracle Database PL/SQLパッケージおよびタイプ・リファレンスを参照
10.6.7 DML競合ハンドラの管理
DML競合ハンドラを設定および削除できます。既存のDML競合ハンドラを変更するには、DML競合ハンドラ削除して再設定する必要があります。
10.6.7.1 DML競合ハンドラの設定
DBMS_APPLY_ADM
パッケージのSET_DML_CONFLICT_HANDLER
プロシージャを使用して、DML競合ハンドラを設定します。
-
RECORD
-
IGNORE
-
OVERWRITE
-
MAXIMUM
-
MINIMUM
-
DELTA
-
MAX_AND_EQUALS
-
MIN_AND_EQUALS
DML競合ハンドラを設定するには、次のようにします。
- インバウンド・サーバー・データベースにXStream管理者として接続します。
DBMS_APPLY_ADM
パッケージのSET_DML_CONFLICT_HANDLER
プロシージャを実行します。
例10-6 DML競合ハンドラの設定
仮にXStreamクライアントが、dbs1.example.com
のhr.jobs
表に適用される変更を受信したとします。この環境では、クライアントが受信する外部データベースからの変更が、ターゲット・データベースdbs1.example.com
への変更と調整されていない可能性があるため、競合が発生する場合があります。特定のDMLの挿入または更新について競合が発生している場合、外部データベースからの変更が、常にターゲット・データベースでの変更を上書きする必要があります。この環境では、dbs1.example.com
データベースでOVERWRITE
ハンドラを指定して、この目標を達成できます。DMLの削除用の行が存在しないため競合が発生している場合、その行LCRは無視されます。
この例では、dbs1.example.com
データベースのhr.jobs
表のためのDML競合ハンドラを指定します。
DECLARE
cols DBMS_UTILITY.LNAME_ARRAY;
BEGIN
cols(1) := 'job_title';
cols(2) := 'min_salary';
cols(3) := 'max_salary';
DBMS_APPLY_ADM.SET_DML_CONFLICT_HANDLER(
apply_name => 'app_jobs',
conflict_handler_name => 'jobs_handler_insert',
object => 'hr.jobs',
operation_name => 'INSERT',
conflict_type => 'ROW_EXISTS',
method_name => 'OVERWRITE',
column_table => cols);
DBMS_APPLY_ADM.SET_DML_CONFLICT_HANDLER(
apply_name => 'app_jobs',
conflict_handler_name => 'jobs_handler_update',
object => 'hr.jobs',
operation_name => 'UPDATE',
conflict_type => 'ROW_EXISTS',
method_name => 'OVERWRITE',
column_table => cols);
DBMS_APPLY_ADM.SET_DML_CONFLICT_HANDLER(
apply_name => 'app_jobs',
conflict_handler_name => 'jobs_handler_delete',
object => 'hr.jobs',
operation_name => 'DELETE',
conflict_type => 'ROW_MISSING',
method_name => 'IGNORE',
column_list => '*');
END;
/
適用プロセスapp_jobs
は指定されたDML競合ハンドラを使用します。
注意:
-
jobs_handler_delete
DML競合ハンドラについては、operation_name
がDELETE
に設定されたときに、すべての列が指定される必要があるため、column_list
パラメータは'*'
に設定されます。 -
クライアントがXStream Outを使用してOracleデータベースからデータを取得する場合は、宛先データベースの
column_list
にあるすべての列について、ソース・データベースで条件付きのサプリメンタル・ログ・グループを指定する必要があります。この例では、外部データベースのhr.jobs
表のjob_title
、min_salary
およびmax_salary
列を含む条件付きのサプリメンタル・ログ・グループを指定します。 -
ビルトインのDML競合ハンドラでは、LOB、
LONG
、LONG RAW
、ユーザー定義型およびOracleが提供する型の列はサポートされません。したがって、SET_DML_CONFLICT_HANDLER
プロシージャを実行するときには、column_list
パラメータにこれらの型の列を含めないでください。
関連項目:
データ型の詳細は、Oracle Database SQL言語リファレンスを参照10.6.7.2 DML競合ハンドラの削除
DBMS_APPLY_ADM
パッケージのSET_DML_CONFLICT_HANDLER
プロシージャを実行すると、既存のDML競合ハンドラを削除できます。
既存のDML競合ハンドラを削除するには、メソッドにNULL
を指定し、既存のDML競合ハンドラと同じ適用名およびDML競合ハンドラ名を指定します。
DML競合ハンドラを削除するには、次のようにします。
- インバウンド・サーバー・データベースにXStream管理者として接続します。
- メソッドに
NULL
を指定してDBMS_APPLY_ADM
パッケージのSET_DML_CONFLICT_HANDLER
プロシージャを実行し、既存のDML競合ハンドラと同じ適用名、DML競合ハンドラ名、オブジェクト名、競合タイプおよび解消列を指定します。
例10-7 DML競合ハンドラの削除
DML競合ハンドラの設定で作成されたDML競合ハンドラを削除するには、次の手順を実行します。
BEGIN
DBMS_APPLY_ADM.SET_DML_CONFLICT_HANDLER(
apply_name => 'app_jobs',
conflict_handler_name => 'jobs_handler_insert',
method_name => NULL);
DBMS_APPLY_ADM.SET_DML_CONFLICT_HANDLER(
apply_name => 'app_jobs',
conflict_handler_name => 'jobs_handler_update',
method_name => NULL);
DBMS_APPLY_ADM.SET_DML_CONFLICT_HANDLER(
apply_name => 'app_jobs',
conflict_handler_name => 'jobs_handler_delete',
method_name => NULL);
END;
/
10.6.8 非キー列の競合検出の停止
DBMS_APPLY_ADM
パッケージのCOMPARE_OLD_VALUES
プロシージャを使用すると、非キー列の競合検出を停止できます。
非キー列の競合検出を停止するには、次のようにします。
- インバウンド・サーバー・データベースにXStream管理者として接続します。
DBMS_APPLY_ADM
パッケージのCOMPARE_OLD_VALUES
プロシージャを実行して、非キー列を指定し、compare
パラメータにFALSE
を指定します。
例10-8 非キー列の競合検出の停止
仮に、hr.employees
表の競合解消用にtime
列を構成したとします。表に変更があるたびに、トリガーによってこの列に現在の時刻が記録されます。この場合、表の他の非キー列の競合検出を停止するように指定できます。hr.employees
表の列を更新競合ハンドラの列リストに追加します。
DECLARE
cols DBMS_UTILITY.NAME_ARRAY;
BEGIN
cols(1) := 'first_name';
cols(2) := 'last_name';
cols(3) := 'email';
cols(4) := 'phone_number';
cols(5) := 'hire_date';
cols(6) := 'job_id';
cols(7) := 'salary';
cols(8) := 'commission_pct';
cols(9) := 'manager_id';
cols(10) := 'department_id';
cols(11) := 'time';
DBMS_APPLY_ADM.SET_DML_CONFLICT_HANDLER(
apply_name => 'app_employees',
conflict_handler_name => 'emp_handler',
object => 'hr.employees',
operation_name => 'UPDATE',
conflict_type => 'ROW_EXISTS',
method_name => 'MAXIMUM',
column_list => cols,
resolution_column => 'time');
END;
/
この例では、主キーに更新がないことを想定しているため、列リストに表の主キーは含まれていません。ただし、他のキー列は列リストに含まれています。
UPDATE
操作に対する表内のすべての非キー列の競合検出を停止するには、次のように入力します。
DECLARE
cols DBMS_UTILITY.LNAME_ARRAY;
BEGIN
cols(1) := 'first_name';
cols(2) := 'last_name';
cols(3) := 'email';
cols(4) := 'phone_number';
cols(5) := 'hire_date';
cols(6) := 'job_id';
cols(7) := 'salary';
cols(8) := 'commission_pct';
DBMS_APPLY_ADM.COMPARE_OLD_VALUES(
object_name => 'hr.employees',
column_table => cols,
operation => '*',
compare => FALSE);
END;
/
operationパラメータに指定されるアスタリスク(*)は、UPDATE
操作について競合検出が停止されたことを意味します。このプロシージャを実行すると、データベース上で実行中の、指定の表に変更をローカルに適用するすべての適用プロセスでは、指定した列の競合は検出されません。したがって、この例では、time
列のみが競合検出に使用されます。
注意:
この項の例では、DML競合ハンドラを設定してから、非キー列の競合検出を停止しています。ただし、非キー列の競合検出を停止する前に、DML競合ハンドラは必要ありません。10.7 適用エラーの管理
インバウンド・サーバーがLCRを適用する際に適用エラーが起きると、エラーが発生します。
適用エラーが発生すると、エラーが発生したLCRおよび同じトランザクション内の他のすべてのLCRがエラー・キューに移動されます。
関連項目:
-
Oracle Enterprise Manager Cloud Controlでの適用エラーの管理については、Oracle Enterprise Manager Cloud Controlのオンライン・ヘルプを参照
10.7.1 インバウンド・サーバーのエラー処理
特定のタイプのエラーを処理するためのエラー・ハンドラを構成できます。
10.7.1.1 エラー・ハンドラについて
エラー・ハンドラは、適用中の特定のエラーを処理するためのメソッドを指定します。
インバウンド・サーバーで行LCRが適用される際、エラーが発生することがあります。DBMS_APPLY
パッケージのSET_REPERROR_HANDLER
プロシージャで指定されたメソッドを使用して、特定のエラーを処理するためのエラー・ハンドラを構成できます。たとえば、行LCRが表に存在しない行を更新または削除しようとしたときに発生するORA-26787エラーを処理するエラー・ハンドラを設定できます。また、特定のエラーを指定せずにデフォルトのエラー処理方法を構成できます。
エラー・ハンドラは、特定の適用プロセスに対して設定します。特定の表またはすべての表に対してエラー・ハンドラを設定できます。
次の表では、各エラー・ハンドラ・メソッドについて説明します。
表10-2 エラー・ハンドラ・メソッド
メソッド | 説明 |
---|---|
ABEND |
エラーが発生した場合、インバウンド・サーバーを停止します。 |
RECORD |
エラーが発生した場合、エラーの原因となった行LCRをエラー・キューに移動します。 |
IGNORE |
エラーが発生した場合、警告を出さずにエラーを無視し、LCR行を適用しません。 |
RETRY |
エラーが発生した場合、指定された回数だけ行LCRを再試行します。 再試行が失敗した場合、トランザクション全体がエラー・キューに移されます。 |
RETRY_TRANSACTION |
エラーが発生した場合、指定された遅延の後に、指定された回数だけトランザクションを再試行します。 再試行が失敗した場合、トランザクション全体がエラー・キューに移されます。 |
RECORD_TRANSACTION |
エラーが発生した場合、トランザクション全体をエラー・キューに移動します。 |
10.7.1.2 エラー・ハンドラの設定および設定解除
DBMS_APPLY
パッケージのSET_REPERROR_HANDLER
プロシージャを使用してエラー・ハンドラを設定します。
-
ABEND
-
RECORD
-
IGNORE
-
RETRY
-
RETRY_TRANSACTION
-
RECORD_TRANSACTION
エラー・ハンドラの設定を解除するには、SET_REPERROR_HANDLER
プロシージャのmethod
パラメータをNULL
に設定します。
エラー・ハンドラを設定または設定解除するには、次のようにします。
- インバウンド・サーバー・データベースにXStream管理者として接続します。
DBMS_APPLY_ADM
パッケージのSET_REPERROR_HANDLER
プロシージャを実行します。
例10-9 特定の表のすべてのエラーについてインバウンド・サーバーを停止するエラー・ハンドラの設定
この例では、oe.orders
表のすべてのエラーについてapp_oe
インバウンド・サーバーを停止するエラー・ハンドラが設定されます。error_number
パラメータを0
に設定すると、すべてのエラーが指定されます。method
パラメータをABEND
に設定すると、エラーの発生時にインバウンド・サーバーが停止することが指定されます。
BEGIN
DBMS_APPLY_ADM.SET_REPERROR_HANDLER(
apply_name => 'app_oe',
object => 'oe.orders',
error_number => 0,
method => 'ABEND');
END;
/
例10-10 特定の表および特定のエラーについて行LCRを無視するエラー・ハンドラの設定
この例では、app_oe
インバウンド・サーバーについてORA-1403エラーが発生する行LCRを無視するエラー・ハンドラを設定します。エラー・ハンドラは、oe.orders
表に適用されます。
BEGIN
DBMS_APPLY_ADM.SET_REPERROR_HANDLER(
apply_name => 'app_oe',
object => 'oe.orders',
error_number => 1403,
method => 'IGNORE');
END;
/
例10-11 エラー・ハンドラの設定解除
この例では、app_oe
インバウンド・サーバーについてORA-1403エラーが発生する行LCRを無視するエラー・ハンドラの設定を解除します。エラー・ハンドラは、oe.orders
表に対して設定されていました。
BEGIN
DBMS_APPLY_ADM.SET_REPERROR_HANDLER(
apply_name => 'app_oe',
object => 'oe.orders',
error_number => 1403,
method => NULL);
END;
/
10.7.2 適用エラー・トランザクションの再試行
特定のエラー・トランザクションだけ、または1つのインバウンド・サーバーのすべてのエラー・トランザクションを再試行できます。
エラー・トランザクションを再試行する前に、データベース・オブジェクトに対してDML変更またはDDL変更を行い、1つ以上の適用エラーの原因となった状態を修正することが必要な場合もあります。
関連項目:
現行セッションで生成されるタグの値の設定の詳細は、Oracle Streamsレプリケーション管理者ガイドを参照
10.7.2.1 特定の適用エラー・トランザクションの再試行
エラー・トランザクションを再試行する場合は、直接実行することも、ユーザー・プロシージャにエラー・トランザクションを送信して変更した後で実行することもできます。
関連項目:
EXECUTE_ERROR
プロシージャの詳細は、Oracle Database PL/SQLパッケージおよびタイプ・リファレンスを参照
10.7.2.1.1 ユーザー・プロシージャを使用しない特定の適用エラー・トランザクションの再試行
適用エラーの原因となった条件を修正した後に、ユーザー・プロシージャを指定せずにDBMS_APPLY_ADM
パッケージのEXECUTE_ERROR
プロシージャを実行して、トランザクションを再試行できます。この場合、トランザクションはカスタム処理を使用せずに実行されます。
複数のエラー・トランザクションがある場合、エラー・トランザクションを実行するときにトランザクションの順序が重要になることがあります。一般的に、最も古いトランザクションを最初に実行し、最新のトランザクションに到達するまでそれぞれの後続のトランザクションを順番に実行するのがベスト・プラクティスです。DBA_APPLY_ERROR
ビューのSOURCE_COMMIT_POSITION
列にはトランザクション時間が表示されます。
ユーザー・プロシージャを使用しない特定の適用エラー・トランザクションの再試行を行うには、次のようにします。
-
SQL*Plusで、データベースにXStream管理者として接続します。
SQL*Plusでのデータベースへの接続の詳細は、Oracle Database管理者ガイドを参照してください。
-
DBMS_APPLY_ADM
パッケージのEXECUTE_ERROR
プロシージャを実行して、トランザクション識別子を指定します。トランザクション識別子が
5.4.312
のトランザクションを再試行するには、次のプロシージャを実行します。BEGIN DBMS_APPLY_ADM.EXECUTE_ERROR( local_transaction_id => '5.4.312', execute_as_user => FALSE, user_procedure => NULL); END; /
execute_as_user
がTRUE
の場合は、インバウンド・サーバーでは、現行ユーザーのセキュリティ・コンテキスト内でトランザクションが実行されます。execute_as_user
がFALSE
の場合、インバウンド・サーバーでは、トランザクションの元の受信者のセキュリティ・コンテキスト内でトランザクションが実行されます。元の受信者とは、エラー発生時にトランザクションを処理していたユーザーです。
いずれの場合も、トランザクションを実行するユーザーには、適用オブジェクトに対するDML変更およびDDL変更を実行するための権限と、任意の適用ハンドラを実行するための権限が必要です。
10.7.2.1.2 ユーザー・プロシージャを使用した特定の適用エラー・トランザクションの再試行
DBMS_APPLY_ADM
パッケージのEXECUTE_ERROR
プロシージャを実行してエラー・トランザクションを再試行できます。また、ユーザー・プロシージャを指定して、トランザクションの実行前に、トランザクション内の1つ以上のLCRを変更することもできます。
この変更によって、トランザクションが正常に実行できるはずです。
たとえば、競合が原因で適用エラーが発生した場合を考えてみます。エラー・トランザクションを検証すると、行LCRのsalary
列の古い値が間違っていることが判明しました。具体的には、hr.employees
表のemployee_id
が197
の従業員について、給料の現行の値が、行LCRにおけるこの従業員の給料の古い値と一致していません。hr.employees
表で、この従業員の現行の値が3250
であるとします。この項の例では、エラーを解消するプロシージャを作成します。
ユーザー・プロシージャを使用した特定の適用エラー・トランザクションの再試行を行うには、次のようにします。
-
SQL*Plusで、データベースにXStream管理者として接続します。
SQL*Plusでのデータベースへの接続の詳細は、Oracle Database管理者ガイドを参照してください。
-
前述したこのシナリオで、エラーの原因となった行LCR内のsalaryを変更する次のユーザー・プロシージャを作成します。
CREATE OR REPLACE PROCEDURE xstrmadmin.modify_emp_salary( in_any IN ANYDATA, error_record IN ALL_APPLY_ERROR%ROWTYPE, error_message_number IN NUMBER, messaging_default_processing IN OUT BOOLEAN, out_any OUT ANYDATA) AS row_lcr SYS.LCR$_ROW_RECORD; row_lcr_changed BOOLEAN := FALSE; res NUMBER; ob_owner VARCHAR2(32); ob_name VARCHAR2(32); cmd_type VARCHAR2(30); employee_id NUMBER; BEGIN IF in_any.getTypeName() = 'SYS.LCR$_ROW_RECORD' THEN -- Access the LCR res := in_any.GETOBJECT(row_lcr); -- Determine the owner of the database object for the LCR ob_owner := row_lcr.GET_OBJECT_OWNER; -- Determine the name of the database object for the LCR ob_name := row_lcr.GET_OBJECT_NAME; -- Determine the type of DML change cmd_type := row_lcr.GET_COMMAND_TYPE; IF (ob_owner = 'HR' AND ob_name = 'EMPLOYEES' AND cmd_type = 'UPDATE') THEN -- Determine the employee_id of the row change IF row_lcr.GET_VALUE('old', 'employee_id') IS NOT NULL THEN employee_id := row_lcr.GET_VALUE('old', 'employee_id').ACCESSNUMBER(); IF (employee_id = 197) THEN -- error_record.message_number should equal error_message_number row_lcr.SET_VALUE( value_type => 'OLD', column_name => 'salary', column_value => ANYDATA.ConvertNumber(3250)); row_lcr_changed := TRUE; END IF; END IF; END IF; END IF; -- Specify that the inbound server continues to process the current message messaging_default_processing := TRUE; -- assign out_any appropriately IF row_lcr_changed THEN out_any := ANYDATA.ConvertObject(row_lcr); ELSE out_any := in_any; END IF; END; /
-
DBMS_APPLY_ADM
パッケージのEXECUTE_ERROR
プロシージャを実行して、トランザクション識別子およびユーザー・プロシージャを指定します。トランザクション識別子が
5.6.924
のトランザクションを再試行する際、実行前にxstrmadmin
スキーマ内のmodify_emp_salary
プロシージャでトランザクションを処理するには、次のプロシージャを実行します。BEGIN DBMS_APPLY_ADM.EXECUTE_ERROR( local_transaction_id => '5.6.924', execute_as_user => FALSE, user_procedure => 'xstrmadmin.modify_emp_salary'); END; /
注意:
プロシージャを実行するユーザーには、ALL_APPLY_ERROR
データ・ディクショナリ・ビューに対するSELECT
権限が必要です。
10.7.2.2 インバウンド・サーバーについてのすべてのエラー・トランザクションの再試行
インバウンド・サーバーについて、すべての適用エラーの原因となった条件を修正した後に、DBMS_APPLY_ADM
パッケージのEXECUTE_ALL_ERRORS
プロシージャを実行してすべてのエラー・トランザクションを再試行できます。
インバウンド・サーバーについてのすべてのエラー・トランザクションを再試行するには、次のようにします。
複数のエラー・トランザクションがある場合、EXECUTE_ALL_ERRORS
プロシージャは最も古いトランザクションを最初に実行し、最新のトランザクションに到達するまでそれぞれの後続のトランザクションを順番に実行します。
-
SQL*Plusで、データベースにXStream管理者として接続します。
SQL*Plusでのデータベースへの接続の詳細は、Oracle Database管理者ガイドを参照してください。
-
DBMS_APPLY_ADM
パッケージのEXECUTE_ALL_ERRORS
プロシージャを実行して、インバウンド・サーバーの名前を指定します。xin
という名前のインバウンド・サーバーについてのエラー・トランザクションを再試行するには、次のプロシージャを実行します。BEGIN DBMS_APPLY_ADM.EXECUTE_ALL_ERRORS( apply_name => 'xin', execute_as_user => FALSE); END; /
注意:
apply_name
パラメータに対してNULL
を指定した場合に、複数のインバウンド・サーバーが存在すると、すべてのインバウンド・サーバーのすべての適用エラーが再試行されます。
10.7.3 適用エラー・トランザクションの削除
インバウンド・サーバーの特定のエラー・トランザクションまたはすべてのエラー・トランザクションを削除できます。
10.7.3.1 特定の適用エラー・トランザクションの削除
エラー・トランザクションを適用する必要がない場合は、DBMS_APPLY_ADM
パッケージのDELETE_ERROR
プロシージャを使用して、エラー・キューからトランザクションを削除できます。
特定の適用エラー・トランザクションを削除するには、次のようにします。
-
SQL*Plusで、データベースにXStream管理者として接続します。
SQL*Plusでのデータベースへの接続の詳細は、Oracle Database管理者ガイドを参照してください。
-
削除するエラー・トランザクションのトランザクションIDを指定します。
たとえば、次の問合せを実行して、ローカル適用エラー・トランザクションのリストを表示します。
COLUMN APPLY_NAME FORMAT A11 COLUMN SOURCE_DATABASE' FORMAT A10 COLUMN LOCAL_TRANSACTION_ID FORMAT A11 COLUMN ERROR_NUMBER FORMAT 99999999 COLUMN ERROR_MESSAGE FORMAT A20 COLUMN MESSAGE_COUNT FORMAT 99999999 SELECT APPLY_NAME, SOURCE_DATABASE, LOCAL_TRANSACTION_ID, ERROR_NUMBER, ERROR_MESSAGE, MESSAGE_COUNT FROM DBA_APPLY_ERROR;
-
DBMS_APPLY_ADM
パッケージのDELETE_ERROR
プロシージャを実行して、トランザクション識別子を指定します。トランザクション識別子が
5.4.312
であるトランザクションを削除するには、次のプロシージャを実行します。EXEC DBMS_APPLY_ADM.DELETE_ERROR(local_transaction_id => '5.4.312');
10.7.3.2 インバウンド・サーバーについてのすべてのエラー・トランザクションの削除
すべてのエラー・トランザクションを適用しない場合は、DBMS_APPLY_ADM
パッケージのDELETE_ALL_ERRORS
プロシージャを実行して、すべてのエラー・トランザクションを削除できます。
インバウンド・サーバーについてのすべてのエラー・トランザクションを削除するには、次のようにします。
-
SQL*Plusで、データベースにXStream管理者として接続します。
SQL*Plusでのデータベースへの接続の詳細は、Oracle Database管理者ガイドを参照してください。
-
DBMS_APPLY_ADM
パッケージのDELETE_ALL_ERRORS
プロシージャを実行して、インバウンド・サーバーの名前を指定します。xin
という名前のインバウンド・サーバーについてのエラー・トランザクションをすべて削除するには、次の手順を実行します。EXEC DBMS_APPLY_ADM.DELETE_ALL_ERRORS(apply_name => 'xin');
注意:
apply_name
パラメータに対してNULL
を指定した場合に、複数のインバウンド・サーバーが存在すると、すべてのインバウンド・サーバーのすべての適用エラーが削除されます。
10.7.4 インバウンド・サーバーで発生した即時エラーの管理
パフォーマンスを最適化するため、インバウンド・サーバーはコミットLCRを受信する前に、即時適用を使用して大規模なトランザクションの適用を開始できます。
即時適用の詳細は、大規模トランザクションにおけるXStream Inのパフォーマンスの最適化を参照してください。
インバウンド・サーバーがトランザクションを即時に適用するとき、エラーが発生する場合があります。すべてのLCRをトランザクションのために使用できないため、この失敗したトランザクションに対してEAGER
ERROR
が記録されます。この場合、ALL_APPLY_ERROR
ビューのエントリにトランザクションの即時エラーが表示されますが、LCRはエラー・キューに記録されません。エラー・トランザクションが即時エラー・トランザクションでない場合は、これは通常エラー・トランザクションと呼ばれます。
通常エラー・トランザクションと即時エラー・トランザクションは、異なる方法で管理する必要があります。インバウンド・サーバーは通常エラー・トランザクションを、そのすべてのLCRを含めてエラー・キューに移しますが、インバウンド・サーバーは即時エラー・トランザクションをエラー・キューに移しません。
即時エラーにより、インバウンド・サーバーは停止します。インバウンド・サーバーが再起動するとき、再起動するトランザクションについてのEAGER
ERROR
がエラー・キューに存在する場合、トランザクションは通常トランザクションとして開始されます。つまり、大規模トランザクションのLCRはディスクに書き出され、インバウンド・サーバーは、コミットLCRを受信して初めてLCRの適用を開始します。
次の文は、通常エラー・トランザクションと即時エラー・トランザクションの両方に適用されます。
-
ALL_APPLY_ERROR
ビューおよびALL_APPLY_ERROR_MESSAGES
ビューには、エラー・トランザクションに関する情報(メタデータ)が含まれています。 -
インバウンド・サーバーはエラー・トランザクションを適用しません。
表10-3は、通常エラー・トランザクションを管理するためのオプションについて説明しています。
表10-3 通常エラー・トランザクションを管理するために使用できるオプション
アクション | メカニズム | 説明 |
---|---|---|
エラー・トランザクションの削除 |
Oracle Enterprise Manager Cloud Control。 |
エラー・トランザクションがエラー・キューから削除され、エラー・トランザクションに関するメタデータが削除されます。インバウンド・サーバーが再起動されたとき、インバウンド・サーバーはトランザクションの再実行を試行しません。トランザクションは適用されません。 |
エラー・トランザクションの実行 |
Oracle Enterprise Manager Cloud Control。 |
エラー・キュー内のエラー・トランザクションが実行されます。実行中にエラーが発生しない場合は、そのトランザクションが適用されます。実行中にLCRでエラーが発生した場合、通常エラー・トランザクションは元のエラー・キューに移動されます。 |
エラー・トランザクションの保持 |
なし。(エラー・トランザクションは自動的に保持されます。) |
エラー・トランザクションは、インバウンド・サーバーが再起動された場合でもエラー・キューに保持されます。エラー・トランザクションに関するメタデータも保持されます。トランザクションは適用されません。 |
表10-4は、即時エラー・トランザクションを管理するためのオプションについて説明しています。
表10-4 即時エラー・トランザクションを管理するために使用できるオプション
アクション | メカニズム | 説明 |
---|---|---|
エラー・トランザクションの削除 |
Oracle Enterprise Manager Cloud Control。 |
即時エラー・トランザクションに関するメタデータが削除されます。インバウンド・サーバーが再起動されると、インバウンド・サーバーはトランザクションを即時トランザクションとして実行しようとします。インバウンド・サーバーの実行中にエラーが発生しない場合、トランザクションは正常に適用されます。インバウンド・サーバーの実行中にエラーが発生した場合、即時エラー・トランザクションが記録されます。 |
エラー・トランザクションの保持 |
なし。(エラー・トランザクションに関するメタデータは自動的に保持されます。) |
即時エラー・トランザクションに関するメタデータは保持されます。インバウンド・サーバーが再起動されると、インバウンド・サーバーはトランザクションを通常トランザクションとして実行しようとします。 具体的には、インバウンド・サーバーはトランザクションをディスクに書き出し、トランザクションの実行を試行します。インバウンド・サーバーの実行中にエラーが発生しない場合、トランザクションは正常に適用されます。インバウンド・サーバーの実行中にエラーが発生した場合、トランザクションは通常エラー・トランザクションになります。この場合、エラーが発生したLCRおよびそのトランザクション内の他のすべてのLCRがエラー・キューに移されます。通常エラー・トランザクションがエラー・キューに移された後は、エラー・トランザクションを(即時エラー・トランザクションではなく)通常エラー・トランザクションとして管理する必要があります。 |
注意:
DBMS_APPLY_ADM
パッケージまたはOracle Enterprise Manager Cloud Controlを使用して即時エラー・トランザクションを手動で実行しようとすると、次のエラーが表示されます。
ORA-26909: cannot reexecute an eager error
即時エラー・トランザクションは手動で実行できません。かわりに、インバウンド・サーバーが有効化されたときに自動的に実行されます。
インバウンド・サーバーで発生した即時エラー・トランザクションを管理するには、次のようにします。
-
インバウンド・サーバー・データベースにXStream管理者として接続します。
SQL*Plusでのデータベースへの接続の詳細は、Oracle Database管理者ガイドを参照してください。
-
ALL_APPLY_ERROR
データ・ディクショナリ・ビューのERROR_TYPE
列を問い合せます。SELECT APPLY_NAME, ERROR_TYPE FROM ALL_APPLY_ERROR;
エラー・タイプに基づいて適切な手順を実行します。
-
ERROR_TYPE
列にEAGER
ERROR
が表示されている場合、手順3に進みます。 -
ERROR_TYPE
列にNULL
が表示されている場合、適用エラーは即時エラーではないため、この項の手順を使用して管理することはできません。かわりに、適用エラー・トランザクションの再試行および適用エラー・トランザクションの削除の手順を使用してください。
-
-
LCRで発生したエラー・メッセージを確認し、エラーの原因を特定します。
関連項目:
-
データ・ディクショナリ・ビューを使用した適用エラー確認の詳細は、適用エラーの確認および適用エラーの詳細情報の表示を参照
-
Oracle Enterprise Manager Cloud Controlを使用した適用エラーの確認については、Oracle Enterprise Manager Cloud Controlのオンライン・ヘルプを参照
-
-
可能であれば、エラーを防止する方法を決定し、エラーを防止するために必要な変更を加えます。
関連項目:
一般的な適用エラーおよびその解決策の詳細は、XStream Inのトラブルシューティングを参照
-
エラー・トランザクションを保持するか、またはエラー・トランザクションを削除します。
-
問題を修正した場合のみエラー・トランザクションを削除します。インバウンド・サーバーが有効化されるとトランザクションが再実行されます。
たとえば、トランザクション識別子が
5.4.312
のトランザクションを削除するには、次のプロシージャを実行します。EXEC DBMS_APPLY_ADM.DELETE_ERROR(local_transaction_id => '5.4.312');
-
問題を今すぐ修正できない場合、または後で再実行する予定がある場合は、エラー・トランザクションを保持します。エラー・トランザクションを保持するためのアクションは必要ありません。再実行されるか削除されるまでエラー・キューに残ります。
これらのオプションの詳細は、表10-4を参照してください。
注意:
削除された通常エラー・トランザクションをリカバリできない可能性があります。エラー・トランザクションを削除する前に、そのエラー・タイプが
EAGER
ERROR
であることを確認してください。関連項目:
-
DBMS_APPLY_ADM
パッケージを使用したエラー・トランザクションの削除の詳細は、適用エラー・トランザクションの削除を参照 -
Oracle Enterprise Manager Cloud Controlを使用したエラー・トランザクションの削除については、Oracle Enterprise Manager Cloud Controlのオンライン・ヘルプを参照してください。
-
-
インバウンド・サーバーが無効な場合、インバウンド・サーバーを起動します。
ALL_APPLY_ERROR
ビューのSTATUS
列を問い合せて、インバウンド・サーバーが有効か無効かを判別します。インバウンド・サーバーについての
disable_on_error
適用パラメータがY
に設定されている場合、インバウンド・サーバーにエラーが発生するとインバウンド・サーバーは無効化され、無効の状態のままになります。インバウンド・サーバーについての
disable_on_error
適用パラメータがN
に設定されている場合は、インバウンド・サーバーにエラーが発生するとインバウンド・サーバーは自動的に停止して再起動します。インバウンド・サーバーが手順5での選択に基づいてエラー・トランザクションを処理する方法については、表10-4を参照してください。
関連項目:
-
DBMS_APPLY_ADM
パッケージを使用したインバウンド・サーバーまたは適用プロセスの起動に関する情報は、インバウンド・サーバーの起動を参照 -
Oracle Enterprise Manager Cloud Controlを使用したインバウンド・サーバーまたは適用プロセスの起動については、Oracle Enterprise Manager Cloud Controlのオンライン・ヘルプを参照
-
注意:
Oracle GoldenGate製品のライセンスを購入し、かつDBMS_XSTREAM_ADM.ENABLE_GG_XSTREAM_FOR_STREAMS
プロシージャを実行してOracle StreamsのXStream最適化が有効になっている場合、Oracle Streams構成の適用プロセスでEAGER
ERROR
タイプのエラーが発生する可能性があります。この項の手順を使用して、即時適用プロセス・エラーを管理してください。Oracle StreamsのXStream最適化が有効になっていない場合、適用プロセスに即時エラーが発生することはありません。
10.8 競合およびエラー処理の優先順位
競合またはエラーを解決するために、インバウンド・サーバーは競合ハンドラおよびエラー・ハンドラを見つけようとします。
競合またはエラーが発生すると、インバウンド・サーバーは、エラーに適用される次のタイプのハンドラを指定された順序でチェックすることで問題を解決しようとします。
-
SET_UPDATE_CONFLICT_HANDLER
プロシージャを使用して設定される更新の競合ハンドラ -
SET_DML_CONFLICT_HANDLER
プロシージャを使用して設定されるカスタム競合ハンドラ -
HANDLE_COLLISIONS
プロシージャを使用して設定される衝突ハンドラ -
SET_REPERROR_HANDLER
プロシージャを使用して設定されるエラー・ハンドラ -
SET_DML_HANDLER
プロシージャを使用して設定されるカスタム競合ハンドラ
これらのプロシージャはすべてDBMS_APPLY_ADM
パッケージにあります。
ハンドラが競合またはエラーに適用されない場合、エラーの原因になったトランザクションはエラー・キューに移動されます。
10.9 XStream In構成内のコンポーネントの削除
DBMS_XSTREAM_ADM
パッケージのDROP_INBOUND
プロシージャを使用して、インバウンド・サーバーを削除できます。
このプロシージャは、指定されたインバウンド・サーバーを常に削除します。また、次の条件が両方満たされている場合、このプロシージャはインバウンド・サーバーのキューも削除します。
-
CREATE_INBOUND
プロシージャへの1回のコールによって、インバウンド・サーバーおよびキューが作成されている。 -
インバウンド・サーバーがこのキューの唯一のサブスクライバである。
前述の条件のいずれかが満たされていない場合、DROP_INBOUND
プロシージャはインバウント・サーバーのみを削除します。キューは削除されません。
インバウンド・サーバーを削除するには、次のようにします。
-
インバウンド・サーバー・データベースにXStream管理者として接続します。
SQL*Plusでのデータベースへの接続の詳細は、Oracle Database管理者ガイドを参照してください。
-
DROP_INBOUND
プロシージャを実行します。
インバウンド・サーバーのキューが自動的に削除されない場合、REMOVE_QUEUE
プロシージャを実行してキューを削除します。
例10-12 インバウンド・サーバーの削除
xin
という名前のインバウンド・サーバーを削除するには、次の手順を実行します。
exec DBMS_XSTREAM_ADM.DROP_INBOUND('xin');
例10-13 インバウンド・サーバーのキューの削除
xin_queue
という名前のキューを削除するには、次のプロシージャを実行します。
exec DBMS_XSTREAM_ADM.REMOVE_QUEUE('xin_queue');