一部のOracle Streams環境では、複数のデータベース間にデータ共有が原因で発生する可能性のあるデータの競合を解消するために、競合ハンドラを使用する必要があります。
この章の内容は次のとおりです。
競合は、LCR内の古い値と、表内の予期されるデータが一致しないことです。複数データベース上で同じデータに対して同時のデータ操作言語(DML)操作を許可しているOracle Streams環境では、競合が発生する可能性があります。Oracle Streams環境でDMLの競合が発生する可能性があるのは、適用プロセスがDML操作によって生じる行の変更を含むメッセージを適用している場合のみです。この種のメッセージは、行の論理変更レコードまたは行LCRと呼ばれます。適用プロセスでは、行LCRが原因で発生する競合が自動的に検出されます。
たとえば、異なるデータベースで発生した2つのトランザクションによって同じ行がほぼ同時に更新されると、競合が発生する場合があります。Oracle Streams環境の構成時には、競合の発生を許可するかどうかを考慮する必要があります。システム設計で競合が許可されている場合は、競合を自動的に解消するように競合解消を構成できます。
通常は、競合の可能性を回避するOracle Streams環境を設計する必要があります。この章で後述する競合防止技法を使用すると、ほとんどのシステム設計で共有データ全体または大部分における競合を防止できます。ただし、多くのアプリケーションでは、複数のデータベースで共有データをある程度の割合まで随時更新可能にする必要があります。この場合は、競合の可能性への対処が必要となります。
注意: 適用プロセスでは、DDLの競合またはユーザー・メッセージによって発生する競合は検出されません。この種の競合が環境で防止されることを確認してください。 |
関連項目: 行LCRの詳細は、『Oracle Streams概要および管理』を参照してください。 |
複数のデータベースでデータを共有する場合は、次のタイプの競合が発生する可能性があります。
更新の競合が発生するのは、適用プロセスで適用される行LCRに含まれている行の更新が、同じ行の他の更新と競合する場合です。また、異なるデータベースからの2つのトランザクションによって、同じ行がほぼ同時に更新される場合にも、更新の競合が発生する可能性があります。
一意性競合が発生するのは、適用プロセスで適用される行LCRに含まれている行の変更が、PRIMARY
KEY
制約やUNIQUE
制約など、一意性の整合性制約に違反している場合です。たとえば、2つの異なるデータベースからの2つのトランザクションがあり、それぞれのトランザクションが同じ主キー値を持つ表に1行を挿入する場合を考えます。この場合は、これらのトランザクションによって一意性競合が発生します。
削除の競合が発生するのは、異なるデータベースで発生した2つのトランザクションがあり、1つのトランザクションで1行を削除し、もう1つのトランザクションで同じ行を更新または削除する場合です。この場合、行LCR内で参照された行は存在せず、更新も削除もできません。
外部キーの競合が発生するのは、適用プロセスで適用される行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
の部門の行が存在しないため、外部キーの競合が発生します。
Oracle Streams環境では、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
で、1つの適用プロセスは、別の適用プロセスがmult3.example.com
でmult1.example.com
から変更の適用を実施する前に、mult2.example.com
から変更の適用を試みます。
この場合、mult3.example.com
での行の列値はmult2.example.com
から伝播した行LCR内の対応する元の値と一致しないため、競合が発生します。
トランザクションが順不同で適用されると、データ競合の原因となるのみでなく、データのサポートがリモート・データベースに正常に伝播されていないと、そのデータベースで参照整合性の問題が発生する場合があります。新規の顧客が受注部門に連絡する場合の使用例を考えます。顧客レコードが作成され、受注が処理されます。リモート・データベースで受注データが顧客データより前に適用されると、受注で参照されている顧客はリモート・データベースに存在しないため、参照整合性エラーが発生します。
順序付けの競合が発生した場合は、必要なデータがリモート・データベースに伝播して適用されてから、エラー・キューにあるトランザクションを再実行すれば、競合を解消できます。
適用プロセスでは、更新、一意性、削除および外部キーの競合が次のように検出されます。
行LCR内の行の元の値と、宛先データベースにある同じ行の現行の値が一致しない場合は、適用プロセスによって更新の競合が検出されます。
挿入または更新操作を含むLCRの適用時に一意制約違反が発生すると、適用プロセスによって一意性競合が検出されます。
更新または削除操作を含むLCRの適用時に、行の主キーが存在しないためにその行が見つからないと、適用プロセスによって削除の競合が検出されます。
LCRの適用時に外部キー制約違反が発生すると、適用プロセスによって外部キーの競合が検出されます。
適用プロセスでLCRを直接適用しようとするか、DMLハンドラなどの適用プロセス・ハンドラでLCRに対してEXECUTE
メンバー・プロシージャを実行すると、競合が検出される場合があります。また、DBMS_APPLY_ADM
パッケージのEXECUTE_ERROR
またはEXECUTE_ALL_ERRORS
プロシージャの実行時にも、競合が検出される場合があります。
注意:
|
この項では、データ競合を防止する方法について説明します。
システム内で、共有データを含む表への同時更新アクセスを行うデータベースの数を制限することによって、競合の可能性を回避できます。プライマリ所有権を使用すると、共有データ・セットへの更新が1つのデータベースにしか許可されないため、すべての競合が防止されます。アプリケーションでは、行と列のサブセットを使用して、データの所有権を表レベルよりも細かく設定できます。たとえば、アプリケーションでは、共有表の特定の列や行への更新アクセス権を、データベースごとに設定できます。
プライマリ・データベース所有権モデルではアプリケーション要件にとって限定的すぎる場合は、共有所有権データ・モデルを使用できますが、これは、競合が発生する可能性があることを意味します。その場合でも、通常は、特定のタイプの競合を回避するためにいくつかの簡単な方法を使用する必要があります。
各データベースで共有データに一意識別子を使用させることで、一意性競合を回避できます。Oracle Streams環境ですべてのデータベースに一意識別子を確実に使用させるには、3つの方法があります。
その1つは、次のSELECT文を実行して一意識別子を構成することです。
SELECT SYS_GUID() OID FROM DUAL;
このSQL演算子は、16バイトのグローバル一意識別子を戻します。この値は、グローバル一意識別子を生成するために時刻、日付およびコンピュータ識別子を使用するアルゴリズムに基づいています。グローバル一意識別子は、次のような書式で表示されます。
A741C791252B3EA0E034080020AE3E0A
また、データを共有する各データベースで順序を作成し、データベース名(または他のグローバル一意値)をローカルの順序と連結して一意性競合を防止する方法もあります。このアプローチを使用すると、重複する順序値を回避し、一意性競合を防止できます。
最後に、2つのデータベースで同じ値を生成できないように、データを共有する各データベースでカスタマイズされた順序を作成する方法があります。そのためには、CREATE
SEQUENCE
文で開始値、増分値および最大値の組合せを使用します。たとえば、次の順序を構成できます。
表9-1 Oracle Streamsレプリケーション環境用にカスタマイズされた順序
パラメータ | データベースA | データベースB | データベースC |
---|---|---|---|
|
1 |
3 |
5 |
|
10 |
10 |
10 |
範囲の例 |
1, 11, 21, 31, 41,... |
3, 13, 23, 33, 43,... |
5, 15, 25, 35, 45,... |
同様のアプローチを使用すると、データベースごとに一意の範囲を生成するSTART
WITH
およびMAXVALUE
を指定して、各データベースに異なる範囲を定義できます。
更新の競合が検出された場合、競合ハンドラではその解消を試みることができます。Oracle Streamsには、更新の競合を解消するためのビルトイン競合ハンドラが用意されていますが、一意性、削除、外部キーまたは順序付けの競合については用意されていません。ただし、ビジネス・ルールに固有のデータ競合を解消するために、独自のカスタム競合ハンドラを作成できます。この種の競合ハンドラは、プロシージャDMLハンドラまたはエラー・ハンドラに付属させることができます。
ビルトイン競合ハンドラとカスタム競合ハンドラのどちらを使用する場合も、競合が検出されるとただちに使用されます。指定した競合ハンドラでも関連する適用ハンドラでも競合を解消できない場合、その競合はエラー・キューに記録されます。競合が発生した場合は、関連する適用ハンドラを使用してデータベース管理者に通知する必要があります。
競合のためにトランザクションがエラー・キューに移動される場合は、競合の原因となった条件を訂正できる場合があります。このような場合は、DBMS_APPLY_ADM
パッケージのEXECUTE_ERROR
プロシージャを使用してトランザクションを再実行できます。
関連項目:
|
この項では、使用可能なビルトインの更新の競合ハンドラのタイプと、この種のハンドラでの列リストと解消列の使用方法について説明します。列リストは、更新の競合がある場合に更新の競合ハンドラがコールされる列のリストです。解消列は、更新の競合ハンドラの識別に使用される列です。ビルトインの更新の競合ハンドラMAXIMUM
またはMINIMUM
を使用する場合は、解消列も競合の解消に使用されます。解消列は、ハンドラの列リスト内の列の1つである必要があります。
特定の表について1つ以上の更新の競合ハンドラを指定するには、DBMS_APPLY_ADM
パッケージのSET_UPDATE_CONFLICT_HANDLER
プロシージャを使用します。一意性競合や削除または外部キーの競合には、ビルトインの競合ハンドラはありません。
関連項目:
|
Oracleには、Oracle Streams環境用にOVERWRITE
、DISCARD
、MAXIMUM
およびMINIMUM
タイプのビルトインの更新の競合ハンドラが用意されています。
後述の各タイプのハンドラの説明では、次の競合例を参照しています。
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
)と一致しないため、競合が発生します。
ここでは、各ビルトイン競合ハンドラと、それぞれがこの競合をどのように解消するかについて説明します。
競合が発生すると、OVERWRITE
ハンドラは、宛先データベースの現行の値をソース・データベースからのLCR内の新規の値で置換します。
OVERWRITE
ハンドラを競合例のdbs2.example.com
宛先データベースのhr.employees
表に使用すると、行LCR内の新規の値によってdbs2.example.com
の値が上書きされます。したがって、競合解消後は、従業員200
の給与は4900
となります。
競合が発生すると、DISCARD
ハンドラはソース・データベースからのLCR内の値を無視し、宛先データベースの値を保持します。
DISCARD
ハンドラを競合例のdbs2.example.com
宛先データベースのhr.employees
表に使用すると、行LCR内の新規の値が廃棄されます。したがって、競合解消後は、dbs2.example.com
での従業員200
の給与は5000
となります。
競合が発生すると、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回起動に設定されていることを確認してください。設定が異なると、適用プロセスによってトランザクションが適用されるときに新規時刻がマークされ、トランザクションの実際時刻が失われる可能性があります。
関連項目: 『Oracle Streams概要および管理』 |
競合が発生すると、MINIMUM
競合ハンドラは、指定された解消列について、ソース・データベースからのLCRにある新規の値を、宛先データベース内の現行の値と比較します。LCRにある解消列の新規の値が宛先データベースの列の現行値より小さければ、適用プロセスではLCRを使用して競合が解消されます。LCRにある解消列の新規の値が宛先データベースの列の現行値より大きければ、適用プロセスでは宛先データベースを使用して競合が解消されます。
MINIMUM
ハンドラを競合例のdbs2.example.com
宛先データベースにあるhr.employees
表のsalary
列に使用すると、行LCRにある給与は表にある現行の給与より小さいため、適用プロセスでは行LCRを使用して競合が解消されます。したがって、競合解消後は、従業員200
の給与は4900
となります。
表に対してビルトインの更新の競合ハンドラを指定するたびに、列リストを指定する必要があります。列リストは、更新の競合ハンドラがコールされる列のリストです。適用プロセスが行LCRを適用するときに、リスト内の1つ以上の列に更新の競合が発生すると、競合を解消するために更新の競合ハンドラがコールされます。リストにない列にのみ競合が発生した場合、更新の競合ハンドラはコールされません。競合解消の有効範囲は、1つの行LCRの1つの列リストです。
特定の表に対して更新の競合ハンドラを複数指定することはできますが、同じ列を複数の列リストに含めることはできません。たとえば、hr.employees
表にビルトインの更新の競合ハンドラを2つ指定する場合を考えます。
最初の更新の競合ハンドラの列リストには、列salary
およびcommission_pct
を指定します。
2番目の更新の競合ハンドラの列リストには、列job_id
およびdepartment_id
を指定します。
また、この表に他の競合ハンドラは存在しないものと想定します。この場合、適用プロセスが行LCRを適用するときにsalary
列に競合が発生すると、それを解消するために最初の更新の競合ハンドラがコールされます。ただし、department_id
列に競合が発生すると、それを解消するために2番目の更新の競合ハンドラがコールされます。どの競合ハンドラの列リストにもない列に競合が発生すると、競合ハンドラはコールされず、エラーになります。この例では、hr.employees
表のmanager_id
列に競合が発生すると、エラーになります。行LCRの適用時に複数の列リストに競合が発生し、列リストにない列での競合がなければ、競合が発生した列リストごとに適切な更新の競合ハンドラが起動されます。
列リストを使用すると、データ型ごとに異なるハンドラを使用して競合を解消できます。たとえば、通常、数値データにはMAXIMUMまたはMINIMUM競合ハンドラが適しており、文字データにはOVERWRITEまたはDISCARD競合ハンドラが適しています。
列リストにない列に競合が発生すると、表に対する特定の操作用のエラー・ハンドラがそれを解消しようとします。エラー・ハンドラが競合を解消できない場合や、この種のエラー・ハンドラがない場合は、競合の原因となったトランザクションがエラー・キューに移動されます。
また、OVERWRITE
、MAXIMUM
またはMINIMUM
ビルトイン・ハンドラのいずれかを使用する列リスト内の列に競合が発生した場合に、この列リスト内のすべての列が行LCRに含まれていないと、使用可能でない値があるため、競合は解消できません。この場合は、競合の原因となったトランザクションがエラー・キューに移動されます。列リストでDISCARD
ビルトイン方法が使用されている場合は、行LCRにこの列リストのすべての列が含まれていない場合にも、行LCRが廃棄され、エラーは発生しません。
ソース・データベースの複数の列が宛先データベースの列リストに影響する場合は、列リストに指定された列に条件付きのサプリメンタル・ログ・グループを指定する必要があります。サプリメンタル・ロギングをソース・データベースで指定し、競合を正しく解消するために必要な情報をLCRに追加します。通常、列リスト内の列に条件付きのサプリメンタル・ログ・グループを指定する必要があるのは、列リストに列が複数存在する場合であり、列リストに存在する列が1つのみの場合は指定する必要ありません。
ただし、列リストに存在する列が1つのみの場合でも、条件付きのサプリメンタル・ログ・グループが必要になることがあります。つまり、適用ハンドラまたはカスタム・ルールベースの変換で、ソース・データベースからの複数列を宛先データベースの列リストの単一行に結合する場合です。たとえば、カスタム・ルールベースの変換で、通り、州および郵便番号を格納するソース・データベースからの3行を使用し、そのデータを宛先データベースで単一の住所列に結合する場合です。
また、列リストに存在する列が複数の場合でも、条件付きのサプリメンタル・ログ・グループが不要なことがあります。たとえば、適用ハンドラまたはカスタム・ルールベースの変換で、ソース・データベースからの単一の住所列を宛先データベースの列リストの複数行に分割する場合です。カスタム・ルールベースの変換で、ソース・データベースの1つの住所列(通り、州および郵便番号を含む)を取得し、そのデータを宛先データベースの3列に分割する場合です。
注意: ビルトインの更新の競合ハンドラでは、LOB、LONG 、LONG RAW 、ユーザー定義型およびOracleが提供する型の列はサポートされません。したがって、SET_UPDATE_CONFLICT_HANDLER プロシージャを実行するときには、column_list パラメータにこれらの型の列を含めないでください。 |
解消列は、ビルトインの更新の競合ハンドラの識別に使用される列です。ビルトインの更新の競合ハンドラMAXIMUM
またはMINIMUM
を使用する場合は、解消列も競合の解消に使用されます。解消列は、ハンドラの列リスト内の列の1つである必要があります。
たとえば、hr.employees
表のsalary
列をMAXIMUMまたはMINIMUM競合ハンドラの解消列として指定すると、行LCR内の列リストの値を適用するか、宛先データベースにおける列リストの値を保持するかを判断するためにsalary
列が評価されます。
競合に解消列が関係する次のどちらの状況でも、エラー・ハンドラで問題を解決できない場合は、適用プロセスは競合の原因となった行LCRを含むトランザクションをエラー・キューに移動します。これらの場合、競合は解消できず、宛先データベースの列の値がそのまま保持されます。
解消列について、新規のLCR値と宛先データベースの行の値が同一の場合(解消列が競合の原因となった列でない場合など)。
解消列の新規のLCR値、または宛先データベースの解消列の現行の値がNULL
の場合。
注意: 解消列は、OVERWRITE およびDISCARD 競合ハンドラには使用されませんが、これらの競合ハンドラ用に指定する必要があります。 |
複数のデータベース間でデータを共有しており、そのすべてでデータを同一にする必要がある場合は、すべてのデータベースでデータを収束させる競合解消ハンドラを使用してください。すべてのデータベースで共有データの変更を許可する場合、表のデータ収束が可能になるのは、データを共有する全データベースが共有データに対する変更を取得し、データを共有する他のすべてのデータベースにその変更を伝播する場合のみです。
このような環境では、MAXIMUM
競合解消方法で収束を保証できるのは、解消列の値が常に増加する場合のみです。時間ベースの解消列は、1行の連続するタイムスタンプが個別である場合に、この要件を満たします。このような環境でMINIMUM
競合解消方法によって収束を保証できるのは、解消列の値が常に減少する場合のみです。
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
パラメータを設定して、競合解消用のプロシージャを指定します。このユーザー・プロシージャは、指定したタイプの操作によって指定した表に生じた競合を解消するためにコールされます。
カスタム競合ハンドラが競合を解消できない場合、適用プロセスは、競合を含むトランザクションをエラー・キューに移動し、そのトランザクションを適用しません。
特定のオブジェクトにビルトインの更新の競合ハンドラとカスタム競合ハンドラの両方が存在する場合は、次の両方の条件が満たされる場合にのみビルトインの更新の競合ハンドラが起動されます。
カスタム競合ハンドラで、LCR用のEXECUTE
メンバー・プロシージャを使用して行LCRが実行される場合。
行LCR用のEXECUTE
メンバー・プロシージャのconflict_resolution
パラメータがTRUE
に設定されている場合。
関連項目:
|
この項では、次のタスクについて説明します。
更新の競合ハンドラを設定するには、DBMS_APPLY_ADM
パッケージのSET_UPDATE_CONFLICT_HANDLER
プロシージャを使用します。更新の競合解消ハンドラを作成する場合は、次のいずれかの事前作成方法を使用できます。
OVERWRITE
DISCARD
MAXIMUM
MINIMUM
たとえば、Oracle Streams環境のdbs1.example.com
でhr.jobs
表に対する変更を取得して、dbs2.example.com
宛先データベースに伝播し、そこで適用する場合を考えます。この環境の場合、アプリケーションでは両方のデータベースのhr.jobs
表に対してDML変更を実行できますが、特定のDML変更に競合がある場合は、dbs1.example.com
データベースでの変更でdbs2.example.com
データベースでの変更を常に上書きする必要があります。この環境では、dbs2.example.com
データベースでOVERWRITE
ハンドラを指定して、この目標を達成できます。
dbs2.example.com
データベースでhr
スキーマ内のhr.jobs
表について更新の競合ハンドラを指定するには、dbs2.example.com
で次のプロシージャを実行します。
DECLARE cols DBMS_UTILITY.NAME_ARRAY; BEGIN cols(1) := 'job_title'; cols(2) := 'min_salary'; cols(3) := 'max_salary'; DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER( object_name => 'hr.jobs', method_name => 'OVERWRITE', resolution_column => 'job_title', column_list => cols); END; /
データベース上で実行中の、指定の表に変更を適用するすべての適用プロセスでは、指定した更新の競合ハンドラがローカルに使用されます。
注意:
|
関連項目:
|
DBMS_APPLY_ADM
パッケージのSET_UPDATE_CONFLICT_HANDLER
プロシージャを実行すると、既存の更新の競合ハンドラを変更できます。既存の競合ハンドラを更新するには、そのハンドラと同じ表および解消列を指定します。
「更新の競合ハンドラの設定」で作成した更新の競合ハンドラを変更するには、hr.jobs
表および解消列としてのjob_title
列を指定します。この更新の競合ハンドラを変更するには、異なるタイプの事前作成方法または異なる列リスト、あるいはその両方を指定できます。ただし、更新の競合ハンドラの解消列を変更するには、ハンドラを削除して再作成する必要があります。
たとえば、環境に変更があり、競合が発生した場合にdbs1.example.com
からの変更を廃棄する必要があるが、dbs1.example.com
からの以前の変更によってdbs2.example.com
の変更が上書きされている場合を考えます。dbs2.example.com
データベースでDISCARD
ハンドラを指定すると、この目標を達成できます。
dbs2.example.com
データベースでhr
スキーマ内のhr.jobs
表について既存の更新の競合ハンドラを変更するには、次のプロシージャを実行します。
DECLARE cols DBMS_UTILITY.NAME_ARRAY; BEGIN cols(1) := 'job_title'; cols(2) := 'min_salary'; cols(3) := 'max_salary'; DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER( object_name => 'hr.jobs', method_name => 'DISCARD', resolution_column => 'job_title', column_list => cols); END; /
DBMS_APPLY_ADM
パッケージのSET_UPDATE_CONFLICT_HANDLER
プロシージャを実行すると、既存の更新の競合ハンドラを削除できます。既存の競合ハンドラを削除するには、メソッドにNULL
を指定し、その競合ハンドラと同じ表、列リストおよび解消列を指定します。
たとえば、「更新の競合ハンドラの設定」で作成し、「既存の更新の競合ハンドラの変更」で変更した更新の競合ハンドラを削除する必要があるとします。この更新の競合ハンドラを削除するには、次のプロシージャを実行します。
DECLARE cols DBMS_UTILITY.NAME_ARRAY; BEGIN cols(1) := 'job_title'; cols(2) := 'min_salary'; cols(3) := 'max_salary'; DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER( object_name => 'hr.jobs', method_name => NULL, resolution_column => 'job_title', column_list => cols); END; /
DBMS_APPLY_ADM
パッケージのCOMPARE_OLD_VALUES
プロシージャを使用すると、非キー列の競合検出を停止できます。
たとえば、hr.employees
表の競合解消用にtime
列を構成すると想定します(「MAXIMUM」を参照)。この場合、表の他の非キー列の競合検出を停止するように指定できます。これを行うには、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_UPDATE_CONFLICT_HANDLER( object_name => 'hr.employees', method_name => 'MAXIMUM', resolution_column => 'time', column_list => cols); END; /
この例では、主キーに更新がないことを想定しているため、列リストに表の主キーは含まれていません。ただし、他のキー列は列リストに含まれています。
宛先データベースでUPDATE
およびDELETE
操作の両方を行う表のすべての非キー列について、競合検出を停止するには、次のプロシージャを実行します。
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
およびDELETE
操作の両方について競合検出が停止されたことを意味します。このプロシージャを実行すると、データベース上で実行中の、指定の表に変更をローカルに適用するすべての適用プロセスでは、指定した列の競合は検出されません。したがって、この例では、time
列のみが競合検出に使用されます。
注意: この項の例では、更新の競合ハンドラを設定してから、非キー列の競合検出を停止しています。ただし、非キー列の競合検出を停止する前に、更新の競合ハンドラは必要ありません。 |
関連項目:
|
ここでは、Streamsレプリケーション環境で適用プロセスを監視するために実行できる問合せについて説明します。
関連項目: 『Oracle Streams概要および管理』 |
DBMS_APPLY_ADM
パッケージのCOMPARE_OLD_VALUES
プロシージャを使用すると、非キー列の競合検出を停止できます。このプロシージャを使用すると、宛先データベースのすべての適用プロセスについて、指定した列の更新および削除の競合検出が停止されます。競合検出が停止された各列を表示するには、次の問合せを実行します。
COLUMN OBJECT_OWNER HEADING 'Table Owner' FORMAT A15 COLUMN OBJECT_NAME HEADING 'Table Name' FORMAT A20 COLUMN COLUMN_NAME HEADING 'Column Name' FORMAT A20 COLUMN COMPARE_OLD_ON_DELETE HEADING 'Compare|Old On|Delete' FORMAT A7 COLUMN COMPARE_OLD_ON_UPDATE HEADING 'Compare|Old On|Update' FORMAT A7 SELECT OBJECT_OWNER, OBJECT_NAME, COLUMN_NAME, COMPARE_OLD_ON_DELETE, COMPARE_OLD_ON_UPDATE FROM DBA_APPLY_TABLE_COLUMNS WHERE APPLY_DATABASE_LINK IS NULL;
出力は次のようになります。
Compare Compare Old On Old On Table Owner Table Name Column Name Delete Update --------------- -------------------- -------------------- ------- ------- HR EMPLOYEES COMMISSION_PCT NO NO HR EMPLOYEES EMAIL NO NO HR EMPLOYEES FIRST_NAME NO NO HR EMPLOYEES HIRE_DATE NO NO HR EMPLOYEES JOB_ID NO NO HR EMPLOYEES LAST_NAME NO NO HR EMPLOYEES PHONE_NUMBER NO NO HR EMPLOYEES SALARY NO NO
注意: Oracle以外のリモート・データベースに適用される変更についての競合検出を停止することもできます。この問合せでは、APPLY_DATABASE_LINK 列がNULL の場合にのみ指定が表示されるため、このような指定は表示されません。 |
DBMS_APPLY_ADM
パッケージのSET_UPDATE_CONFLICT_HANDLER
プロシージャを使用して更新の競合ハンドラを指定した場合は、関連する競合が発生すると、そのハンドラがデータベース内のすべての適用プロセスに対して実行されます。
この項で説明する問合せを実行すると、ビルトインの更新の競合ハンドラを使用して競合解消が指定されている列がすべて表示されます。つまり、データベース内で指定されているすべての列リストの列が表示されます。また、この問合せでは、指定されているビルトインの競合ハンドラの型と、列リストに指定されている解消列も表示されます。
データベース内のすべての更新の競合ハンドラに関する情報を表示するには、次の問合せを実行します。
COLUMN OBJECT_OWNER HEADING 'Table|Owner' FORMAT A5 COLUMN OBJECT_NAME HEADING 'Table Name' FORMAT A12 COLUMN METHOD_NAME HEADING 'Method' FORMAT A12 COLUMN RESOLUTION_COLUMN HEADING 'Resolution|Column' FORMAT A13 COLUMN COLUMN_NAME HEADING 'Column Name' FORMAT A30 SELECT OBJECT_OWNER, OBJECT_NAME, METHOD_NAME, RESOLUTION_COLUMN, COLUMN_NAME FROM DBA_APPLY_CONFLICT_COLUMNS ORDER BY OBJECT_OWNER, OBJECT_NAME, RESOLUTION_COLUMN;
出力は次のようになります。
Table Resolution Owner Table Name Method Column Column Name ----- ------------ ------------ ------------- ------------------------------ HR COUNTRIES MAXIMUM TIME COUNTRY_NAME HR COUNTRIES MAXIMUM TIME REGION_ID HR COUNTRIES MAXIMUM TIME TIME HR DEPARTMENTS MAXIMUM TIME DEPARTMENT_NAME HR DEPARTMENTS MAXIMUM TIME LOCATION_ID HR DEPARTMENTS MAXIMUM TIME MANAGER_ID HR DEPARTMENTS MAXIMUM TIME TIME