ヘッダーをスキップ
Oracle® Streams概要および管理
11gリリース2 (11.2)
B61351-03
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

10 適用プロセスの高度な概念

次の各項では、Oracle Streamsでの情報のコンシュームについて説明します。

適用プロセスの作成

適用プロセスは、DBMS_STREAMS_ADMパッケージまたはDBMS_APPLY_ADMパッケージを使用して作成できます。DBMS_STREAMS_ADMパッケージを使用すると、一部の構成オプションにデフォルトが自動的に使用されるため、適用プロセスをより簡単に作成できます。DBMS_APPLY_ADMパッケージを使用すると、適用プロセスをより柔軟に作成できます。

DBMS_APPLY_ADMパッケージのCREATE_APPLYプロシージャを実行して適用プロセスを作成する場合は、apply_capturedapply_database_linkおよびapply_tagパラメータに対してデフォルト以外の値を指定できます。これによって、DBMS_STREAMS_ADMパッケージまたはDBMS_RULE_ADMパッケージのプロシージャを使用して、適用プロセスのルール・セットにルールを追加できます。

1つのデータベースに複数の適用プロセスを作成した場合、これらの適用プロセスは完全に独立したものになります。同じソース・データベースからのLCRを適用する場合でも、これらの適用プロセスが相互に同期化することはありません。

表10-1に、適用プロセスの作成にDBMS_STREAMS_ADMパッケージを使用した場合とDBMS_APPLY_ADMパッケージを使用した場合の相違点を示します。

表10-1 DBMS_STREAMS_ADMを使用した場合とDBMS_APPLY_ADMを使用した場合の適用プロセスの作成

DBMS_STREAMS_ADMパッケージ DBMS_APPLY_ADMパッケージ

適用プロセスに対して自動的にルール・セットが作成され、このルール・セットに対して自動的にルールを追加することができます。ルール・セットは、inclusion_ruleパラメータがTRUE(デフォルト)に設定されている場合はポジティブ・ルール・セットになります。inclusion_ruleパラメータがFALSEに設定されている場合はネガティブ・ルール・セットになります。適用プロセスの作成後は、DBMS_STREAMS_ADMおよびDBMS_RULE_ADMパッケージのプロシージャを使用して適用プロセスのルール・セットおよびルールを管理できます。

適用プロセスの作成前または作成後に、適用プロセスに対して1つ以上のルール・セットおよびルールを作成します。DBMS_RULE_ADMパッケージのプロシージャを使用すると、適用プロセスの作成前または作成後に適用プロセスに対してルール・セットおよびルールを作成できます。DBMS_STREAMS_ADMパッケージのプロシージャを使用すると、適用プロセスの作成後に適用プロセスに対してルール・セットおよびルールを作成できます。

適用プロセスでは、ローカル・データベースでのみメッセージを適用できます。

適用プロセスの作成時に、ローカル・データベースまたはリモート・データベースのいずれでメッセージを適用するかを指定します。

適用プロセスによって適用された変更によって、宛先データベースのREDOログに、値が00(ゼロが2つ)のタグが生成されます。

適用プロセスの作成時に、適用プロセスによって適用された変更に対するタグ値を指定します。タグのデフォルト値は、00(ゼロが2つ)です。



関連項目:

  • 適用プロセスを作成する方法の詳細は、『Oracle Streamsレプリケーション管理者ガイド』を参照

  • Oracle Streamsタグの詳細は、『Oracle Streamsレプリケーション管理者ガイド』を参照


適用プロセスおよび依存性

次の各項では、適用プロセスで依存性が処理される仕組みについて説明します。

依存トランザクションが適用される仕組み

parallelism適用プロセス・パラメータでは、適用プロセスの並列性を制御します。適用プロセスの並列性が1に設定されている場合、単一の適用サーバーによってトランザクションがソース・データベースでのコミット順に適用されます。この場合、依存性は問題になりません。たとえば、ソース・データベースでトランザクションAがトランザクションBより前にコミットされた場合、宛先データベースでは、トランザクションA内のすべてのLCRがトランザクションB内のどのLCRよりも前に適用されます。

ただし、適用プロセスの並列性の値が2以上に設定されている場合、複数の適用サーバーによってトランザクションが同時に適用されます。適用プロセスによってトランザクションがパラレルで適用される場合、これらのトランザクション内の行LCRが適用された後で、別のトランザクション内の行LCRに依存する行LCRが検出されます。依存する行LCRが検出されると、コミット・システム変更番号(CSCN)が小さいトランザクション内のLCRの適用が終了し、このトランザクションがコミットされてから、CSCNが大きいトランザクション内の残りの行LCRの適用が終了します。

たとえば、トランザクションAとトランザクションBの2つのトランザクションを考えます。これらのトランザクションは依存トランザクションであり、各トランザクションにはそれぞれ100個の行LCRが含まれています。ソース・データベースでは、トランザクションAがトランザクションBより前にコミットされました。したがって、2つのトランザクションのうちCSCNが小さいのはトランザクションAです。適用プロセスでは、これらのトランザクションを次のようにパラレルで適用できます。

  1. 適用プロセスは、両方のトランザクション内の行LCRをパラレルで適用し始めます。

  2. 適用プロセスは、宛先データベースのデータ・ディクショナリの制約または宛先データベースの仮想依存性定義に基づいて、トランザクションA内の行LCRとトランザクションB内の行LCRの依存性を検出します。

  3. 2つのトランザクションのうちCSCNが大きいのはトランザクションBであるため、適用プロセスはトランザクションBの適用を遅らせ、トランザクションB内の依存する行LCRについては適用しません。トランザクションB内の依存する行LCRより前の行LCRは適用されます。たとえば、トランザクションB内の依存する行LCRが81番目の行LCRである場合、適用プロセスはトランザクションB内の100個の行LCRのうち80個を適用することになります。

  4. 2つのトランザクションのうちCSCNが小さいのはトランザクションAであるため、適用プロセスはトランザクションA内のすべての行LCRを適用してコミットします。

  5. 適用プロセスは、トランザクションB内の依存する行LCRを適用し、さらに残りの行LCRを適用します。トランザクションB内のすべての行LCRが適用されたら、適用プロセスはトランザクションBをコミットします。


注意:

parallelism適用プロセス・パラメータは、DBMS_APPLY_ADMパッケージのSET_PARAMETERプロシージャを使用して設定できます。

適用時の行LCRの順序付け

適用プロセスでは、次のように行LCRを順序付けして適用します。

  • 単一のトランザクション内の行LCRは、常にソース・データベースでの対応する変更と同じ順序で適用されます。

  • 異なるトランザクション内の相互に依存する行LCRは、常にソース・データベースでの対応する変更と同じ順序で適用されます。適用プロセスの並列性が2以上であり、適用プロセスで異なるトランザクション内の行LCR間の依存性が検出された場合、常にCSCNが小さいトランザクションが実行されてから、依存する行LCRが実行されます。この動作の詳細は、「依存トランザクションが適用される仕組み」を参照してください。

  • commit_serialization適用プロセス・パラメータがFULLに設定されている場合、依存する行LCRの有無に関係なく、すべてのトランザクションがソース・データベースの対応するトランザクションと同じ順序でコミットされます。

  • commit_serialization適用プロセス・パラメータがDEPENDENT_TRANSACTIONSに設定されている場合、相互に依存しないトランザクションは、ソース・データベースの対応するトランザクションのコミット順とは異なる順序で適用されることがあります。


注意:

commit_serialization適用プロセス・パラメータは、DBMS_APPLY_ADMパッケージのSET_PARAMETERプロシージャを使用して設定できます。

依存性および制約

ソース・データベースと宛先データベースで共有データベース・オブジェクトの名前が同じ場合、かつこれらのデータベースでオブジェクトが同じスキーマ内に含まれている場合、適用プロセスでは、宛先データベースのデータベース・オブジェクトに対して制約が定義されていると仮定して、行LCR間の依存性が自動的に検出されます。これらの制約に関する情報は、宛先データベースのデータ・ディクショナリに格納されています。

適用プロセスでは、commit_serializationパラメータおよび適用プロセスの並列性の設定に関係なく、データベース制約によって強制されるトランザクション間の依存性が常に重視されます。適用対象のトランザクション内の行LCRが別のトランザクション内の行LCRに依存している場合、適用プロセスでは、依存性を維持するために、行LCRが確実に正しい順序で適用され、トランザクションが確実に正しい順序でコミットされます。適用プロセスでは、取得行LCRと永続行LCRの依存性が検出されます。

ただし、環境によっては、データベース制約によって強制されない依存性が存在することもあります。たとえば、アプリケーションを使用して依存性を強制する環境などです。共有データベース・オブジェクトの依存性がデータベース制約によって強制されない環境を使用している場合は、これらのデータベース・オブジェクトに変更を適用する適用プロセスに対してcommit_serializationパラメータをFULLに設定します。

依存性検出、ルールベースの変換および適用ハンドラ

適用プロセスで使用されるルールに対してルールベースの変換が指定されていて、その適用プロセスに適用ハンドラが構成されている場合、LCRは次の順序で処理されます。

  1. 適用プロセスは、そのキューからLCRをデキューします。

  2. 適用プロセスは、LCRに対してルールベースの変換を実行します(適切な場合)。

  3. 適用プロセスは、LCR間の依存性を検出します。

  4. 適用プロセスは、LCRを適用ハンドラに渡します(適切な場合)。

仮想依存性定義

適用プロセスでは、パラレルで適用される行LCR間の依存性を検出するために、追加の情報が必要になる場合があります。次に、依存性を検出するために適用プロセスで追加の情報が必要になる場合の例を示します。

  • 宛先データベースのデータ・ディクショナリに必要な情報が含まれていない場合。たとえば、次のような場合が該当します。

    • 適用プロセスで、宛先データベースのデータ・ディクショナリでデータベース・オブジェクトに関する情報を検出できない場合。このような状況は、ソース・データベースと宛先データベースの間で共有データベース・オブジェクトのデータ・ディクショナリが異なる場合に発生します。たとえば、ソース・データベースと宛先データベースで共有データベース・オブジェクトの名前が異なっていたり、共有データベース・オブジェクトが異なるスキーマに含まれている場合があります。

    • 2つ以上の表が関係していて、その関係が宛先データベースのデータ・ディクショナリに記録されていない場合。このような状況は、パフォーマンスを向上させるためのデータベース制約が定義されていない場合や、データベースの操作中にデータベース制約のかわりにアプリケーションによって依存性が強制される場合に発生します。

  • 依存性の計算後に適用ハンドラによってデータが非正規化される場合。たとえば、単一の行LCR内の情報を使用して、複数の表に適用される複数の行LCRを作成できます。

適用プロセスで依存性を適切に判別できない場合、適用エラーが発生したり、不適切な処理が行われることがあります。前述のような一部の状況においては、ルールベースの変換を使用して、適用の問題を回避できます。たとえば、ソース・データベースと宛先データベースで共有データベース・オブジェクトが異なるスキーマに含まれている場合、ルールベースの変換を使用して、該当するLCRのスキーマを変更できます。ただし、ルールベースの変換はパラレルで実行できないというデメリットがあります。

仮想依存性定義とは、宛先データベースでトランザクション間の依存性を検出するために、適用プロセスで使用される依存性の記述です。仮想依存性定義は、宛先データベースのデータ・ディクショナリの制約としては記述されません。かわりに、DBMS_APPLY_ADMパッケージのプロシージャを使用して指定されます。仮想依存性定義を使用すると、適用プロセスで、データ・ディクショナリの制約情報のみを使用した場合には検出できない依存性を検出できるようになります。依存性が検出されると、適用プロセスは、LCRおよびトランザクションを正しい順序で適用するようにスケジュールします。

仮想依存性定義は、適用プロセスがLCRを直接適用したり、LCRを適用ハンドラに渡す前に、その依存性を正しく検出できるようにするために必要な情報を提供します。仮想依存性定義を使用すると、適用ハンドラでこれらのLCRを正しく処理できるようになります。また、適用ハンドラでLCRをパラレルで処理してパフォーマンスを向上させることができます。

仮想依存性定義では、次の依存性タイプのいずれかを定義できます。


注意:

仮想依存性定義を指定するには、宛先データベースでOracle Database 10g リリース2以上が実行されている必要があります。

値の依存性

値の依存性では、一意キーなどの表制約、または2つ以上の表の列間の関係を定義します。値の依存性は1つ以上の列に対して設定され、適用プロセスでは値の依存性を使用して、これらの列の値を含む行LCR間の依存性を検出します。値の依存性では、表間の仮想外部キー関係を定義できますが、外部キー関係とは異なり、3つ以上の表を対象とすることができます。

値の依存性は、表の列間の関係が宛先データベースのデータ・ディクショナリの制約で記述されていない場合に役立ちます。値の依存性ではこれらの関係が記述され、適用プロセスではこれらの値の依存性を使用して、異なるトランザクション内の2つ以上の行LCRが宛先データベースの表の同じ行に関連していることが判別されます。パラレルで適用されるトランザクションでは、2つ以上の行LCRが同じ行に関連している場合、これらの行LCRを含むトランザクションは依存トランザクションになります。

宛先データベースで値の依存性を定義または削除するには、DBMS_APPLY_ADMパッケージのSET_VALUE_DEPENDENCYプロシージャを使用します。このプロシージャでは、表の列を属性として指定します。

値の依存性には、次の制限事項が適用されます。

  • 値の依存性に指定されたデータベース・オブジェクトに関連する行LCRは、1つのソース・データベースから生成する必要があります。

  • それぞれの値の依存性には、特定のデータベース・オブジェクトに対する1つの属性セットのみを含める必要があります。

また、宛先データベースの値の依存性に指定されたすべての列に対して、ソース・データベースでサプリメンタル・ロギングを実行する必要があります。これらの列は、無条件でログに記録する必要があります。

オブジェクトの依存性

オブジェクトの依存性では、宛先データベースの2つのオブジェクト間の親子関係を定義します。適用プロセスでは、コミット・システム変更番号(CSCN)の値が小さく、親オブジェクトを含むすべてのトランザクションのコミット後に、子オブジェクトを含むトランザクションが実行されるようにスケジュールします。適用プロセスでは、各行LCR内のオブジェクト識別子を使用して依存性を検出します。適用プロセスでは、オブジェクトの依存性を検出するために、行LCR内の列の値を使用しません。

オブジェクトの依存性は、表間の関係が宛先データベースのデータ・ディクショナリの制約で記述されていない場合に役立ちます。オブジェクトの依存性ではこれらの関係が記述され、適用プロセスではこれらのオブジェクトの依存性を使用して、異なるトランザクション内の2つ以上の行LCRがこれらの表に関連していることが判別されます。パラレルで適用されるトランザクションでは、あるトランザクション内の行LCRが子の表に関連し、別のトランザクション内の行LCRが親の表に関連している場合、これらの行LCRを含むトランザクションは依存トランザクションになります。

宛先データベースでオブジェクトの依存性を作成するには、CREATE_OBJECT_DEPENDENCYプロシージャを使用します。宛先データベースでオブジェクトの依存性を削除するには、DROP_OBJECT_DEPENDENCYプロシージャを使用します。これらのプロシージャは、いずれもDBMS_APPLY_ADMパッケージに含まれています。


注意:

適用プロセスの並列性が2以上のときに表の循環依存が存在する場合、適用プロセスのデッドロックが発生する可能性があります。循環依存の例には、表Aが表Bに対する外部キー制約を持ち、表Bが表Aに対する外部キー制約を持つ場合があります。循環依存関係にある表を含む2つ以上のトランザクションが同じSCNでコミットされると、適用プロセスのデッドロックが発生する可能性があります。

バリア・トランザクション

適用プロセスで宛先データベースのデータ・ディクショナリおよび仮想依存性定義を使用して、行LCRに指定された表の行またはデータベース・オブジェクトを識別できない場合、その行LCRを含むトランザクションは、CSCN値が小さい他のすべてのトランザクションが適用された後で適用されます。このようなトランザクションはバリア・トランザクションと呼ばれます。バリア・トランザクションよりCSCN値が大きいトランザクションは、バリア・トランザクションがコミットされるまで適用されません。また、DDLトランザクションはいずれもバリア・トランザクションです。

表へのDML変更の適用に関する考慮事項

次の各項では、表へのDML変更の適用に関する考慮事項について説明します。

制約と表に対するDML変更の適用

宛先データベースの主キー列が、更新のたびにソース・データベースのREDOログに確実に記録されるようにする必要があります。ソース・データベースの複数列のデータが含まれる宛先データベースの一意キー制約または外部キー制約には、ソース・データベースでの追加ロギングが必要です。

列をソース・データベースのログに確実に記録させるには、様々な方法があります。たとえば、列の値が更新されるたびに、その列がログに記録されます。また、Oracleには、指定した列のロギングを自動化するサプリメンタル・ロギングと呼ばれる機能があります。

ソース・データベースの単一列のデータのみが含まれる宛先データベースの一意キー制約と外部キー制約については、サプリメンタル・ロギングは不要です。ただし、ソース・データベースの複数列のデータが含まれる制約については、宛先データベースの制約で使用されるソース・データベースのすべての列が含まれる条件付きのサプリメンタル・ログ・グループを作成する必要があります。

通常、一意キー制約と外部キー制約には、ソース・データベースおよび宛先データベースで同じ列が含まれます。ただし、適用ハンドラまたはカスタム・ルールベースの変換により、ソース・データベースの複数列制約が宛先データベースの単一キー列に結合される場合があります。また、適用ハンドラまたはカスタム・ルールベースの変換により、ソース・データベースの単一キー列が宛先データベースの複数列制約に分割される場合があります。このような場合は、ソース・データベースの制約内の列数により、条件付きのサプリメンタル・ログ・グループが必要かどうかが決定されます。ソース・データベースの制約に複数の列が存在する場合、ソース・データベースに、すべての制約列が含まれる条件付きのサプリメンタル・ログ・グループが必要です。ソース・データベースの制約に1列のみが存在する場合、キー列にサプリメンタル・ロギングは不要です。


関連項目:

サプリメンタル・ロギングの詳細は、『Oracle Streamsレプリケーション管理者ガイド』を参照

代替キー列

可能な場合は、適用プロセスによって変更が適用される各表に主キーを用意する必要があります。主キーを使用できない場合は、各表に各行の一意識別子として使用できる列セットを含めることをお薦めします。Oracle Streams環境で使用する予定の表に主キーまたは一意列セットがない場合は、これらの表を適宜変更することを検討してください。

Oracleは、競合を検出してエラーを正確に処理するために、異なるデータベースで対応する行を一意に識別して一致させることができる必要があります。デフォルトでは、Oracle Streamsは、表の主キーを使用して表の各行を識別します。主キーが存在しない場合は、少なくとも1つのNOT NULL列を持つ最小の一意キーを使用して、表内の行を識別します。宛先データベースの表に主キーまたは少なくとも1つのNOT NULL列を持つ一意キーがない場合や、主キーまたは一意キー以外の列をキーとして使用する必要がある場合は、宛先データベースで代替キーを指定できます。代替キーとは、Oracleが適用中に表の各行を識別するために使用できる列または列セットです。

表の代替主キーを指定するには、DBMS_APPLY_ADMパッケージのSET_KEY_COLUMNSプロシージャを使用します。主キーとは異なり、代替キー列にはNULLを指定できます。また、代替キー列は、宛先データベースのすべての適用プロセスについて、指定された表の既存の主キーまたは一意キーよりも優先されます。

宛先データベースで表の代替キーを指定する場合に、これらの列がソース・データベースの同じ表の主キーでなければ、ソース・データベースで代替キー列を含む無条件のサプリメンタル・ログ・グループを作成する必要があります。

代替キー列、主キー制約および一意キー制約がない場合、適用プロセスでは、LOB、LONGLONG RAW、ユーザー定義型(オブジェクト型、REF、VARRAY、ネストした表など)、およびOracle提供の型(Any型、XML型、空間型、メディア型など)の各データ型の列を除く、表内のすべての列がキー列として使用されます。この場合、ソース・データベースでこれらの列を含む無条件のサプリメンタル・ログ・グループを作成する必要があります。行LCRでは必要な列が少ないため、表の主キー制約がない場合は代替キー列を使用することをお薦めします。


注意:

  • 代替キー列として指定する各列はNOT NULL列にすることをお薦めします。また、代替キーにすべての列を含む1つの索引を作成する必要があります。これらのガイドラインに従うと、データベースでは関連する行を効率的に検索できるため、変更のパフォーマンスが向上します。

  • LOB、LONGLONG RAW、ユーザー定義型およびOracle提供の型の列は、代替キー列として指定できません。



関連項目:

  • 『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』DBMS_APPLY_ADM.SET_KEY_COLUMNSプロシージャ

  • サプリメンタル・ロギングの詳細は、『Oracle Streamsレプリケーション管理者ガイド』を参照

  • データ型の詳細は、『Oracle Database SQL言語リファレンス』を参照

  • 「表の代替キー列の管理」


列の不一致に対する適用プロセスの動作

列の不一致とは、ソース・データベースの表の列と宛先データベースの同じ表の列が一致しないことです。Oracle Streams環境に列の不一致がある場合は、ルールベースの変換、文DMLハンドラまたはプロシージャDMLハンドラを使用して、適用プロセスで適用される行LCRの列を宛先データベースにある関連表の列と一致させます。

次の各項では、一般的な列の不一致に対する適用プロセスの動作について説明します。


関連項目:


宛先データベースの列の欠落

ソース・データベースの表にある1つ以上の列が宛先データベースの表から欠落していると、適用プロセスにエラーが発生し、エラーの原因となったトランザクションがエラー・キューに移動します。この種のエラーは、適用前に欠落している列をLCRから削除するルールベースの変換またはプロシージャDMLハンドラを作成することで回避できます。具体的には、変換またはハンドラでは、行LCRに対してDELETE_COLUMNメンバー・プロシージャを使用して、余分な列を削除できます。また、欠落している列を除外するSQL文を使用する文DMLハンドラを作成することもできます。

宛先データベースの余分な列

宛先データベースの表の列数がソース・データベースの表よりも多い場合、適用プロセスの動作は余分な列が依存性の計算に必要かどうかに応じて異なります。余分な列が依存性の計算に使用されない場合、適用プロセスでは変更が宛先の表に適用されます。この場合、宛先データベースに余分な列に関する列のデフォルトが存在すると、すべての挿入でこれらの列にはデフォルトが使用されます。それ以外の場合、挿入されるこれらの列はNULLになります。

ただし、余分な列が依存性の計算に使用される場合、適用プロセスではこれらの変更を含むトランザクションがエラー・キューに置かれます。依存性の計算には、次のタイプの列が必要です。

  • どのような変更の場合も、すべてのキー列

  • INSERTおよびDELETE文の場合は、制約に関係するすべての列

  • UPDATE文の場合は、一意キー制約列や外部キー制約列などの制約列に変更があれば、その制約に関係するすべての列

余分な列が依存性の計算に使用される場合、適用エラーを回避する方法の1つは、文DMLハンドラを使用して余分な列を追加することです。


関連項目:

「文DMLハンドラ」

列のデータ型の不一致

宛先データベースにある表の列のデータ型が、ソース・データベースにある同じ列のデータ型と一致しない場合は、列のデータ型の不一致が発生します。列のデータ型の不一致が発生すると、適用プロセスでは特定のデータ型を自動的に変換できます。適用プロセスでデータ型を自動的に変換できない場合、不一致の列に対する変更を含むトランザクションがエラー・キューに格納されます。この種のエラーを回避するために、データ型を変換するカスタム・ルールベースの変換またはDMLハンドラを作成できます。

競合解決と適用プロセス

複数のデータベース間でデータが共有されるOracle Streams構成では、競合が発生する可能性があります。競合とは、LCR内の古い値と表内の予期されるデータの不一致です。変更の取得対象となる表とこれらの変更が適用される表について、DML変更が許可されている場合は、競合が発生する可能性があります。

たとえば、ソース・データベースのトランザクションによって行が更新されるのとほぼ同時に、それと同じ行が宛先データベースの異なるトランザクションによって更新されることがあります。この場合、2つのデータベース間でデータの整合性が重要であれば、変更が宛先データベースに伝播されるときに、適用プロセスに対して、宛先データベースで変更を保持するか、ソース・データベースからの変更で置換するように指示する必要があります。データの競合が発生した場合は、競合をビジネス・ルールに従って確実に解決するメカニズムが必要です。

Oracle Streamsでは、競合を自動的に検出し、更新の競合の場合は、更新の競合ハンドラが構成されていれば、それを使用して解決しようとします。Oracle Streamsには様々なビルトイン・ハンドラが用意されており、ビジネス・ルールに従って競合を解決する競合解決システムをデータベースに対して定義できます。ビルトイン競合解決ハンドラで解決できない固有の状況がある場合は、独自のカスタム競合解決ハンドラを作成してエラー・ハンドラまたはプロシージャDMLハンドラ内で使用できます。競合検出は非キー列では無効な場合があります。


関連項目:

『Oracle Streamsレプリケーション管理者ガイド』

ハンドラと行LCRの処理

次のどのハンドラでも、行LCRを処理できます。

  • DMLハンドラ(文DMLハンドラまたはプロシージャDMLハンドラのいずれか)

  • エラー・ハンドラ

  • 更新の競合ハンドラ

次の各項では、これらのハンドラに関係する使用例について説明します。


関連項目:


関連ハンドラがない場合

行LCRに対する関連ハンドラがない場合、適用プロセスは行LCRで指定された変更を直接適用しようとします。適用プロセスが行LCRを適用できる場合は、表のその行が変更されます。適用中に競合またはエラーが発生すると、その行LCRを含むトランザクションがロールバックされ、適用プロセスのルール・セットに従って適用される必要があるトランザクション内のLCRは、すべてエラー・キューに移動します。

関連する更新の競合ハンドラがある場合

関連する更新の競合ハンドラは構成されているが、他の関連ハンドラが構成されていない場合を考えます。適用プロセスは、行LCRで指定された変更を直接適用しようとします。適用プロセスが行LCRを適用できる場合は、表のその行が変更されます。

適用中に、一意性競合や削除の競合など、更新の競合以外の条件によってエラーが発生すると、その行LCRを含むトランザクションがロールバックされ、適用プロセスのルール・セットに従って適用される必要があるトランザクション内のLCRは、すべてエラー・キューに移動します。

適用中に更新の競合が発生すると、関連する更新の競合ハンドラが起動します。更新の競合ハンドラによって競合が正常に解決されると、適用プロセスは更新の競合の解決方法に応じてLCRを適用または廃棄し、適用プロセスのルール・セットに従って適用される必要があるトランザクション内の他のLCRを引き続き適用します。更新の競合ハンドラが競合を解決できない場合は、その行LCRを含むトランザクションがロールバックされ、適用プロセスのルール・セットに従って適用される必要があるトランザクション内のLCRは、すべてエラー・キューに移動します。

DMLハンドラはあるが関連する更新の競合ハンドラがない場合

適用プロセスが行LCRをDMLハンドラに渡し、関連する更新の競合ハンドラが構成されていない場合を考えます。DMLハンドラは、文DMLハンドラとプロシージャDMLハンドラのどちらでもかまいません。

DMLハンドラによって行LCRが処理されます。DMLハンドラのデザイナがこの処理を全面的に制御します。一部のDMLハンドラは、SQL操作を実行するか、行LCRのEXECUTEメンバー・プロシージャを実行する場合があります。DMLハンドラが行LCRのEXECUTEメンバー・プロシージャを実行すると、適用プロセスは行LCRを適用しようとします。この行LCRは、DMLハンドラによって変更されている可能性があります。

文DMLハンドラの失敗

適用プロセスでは、同じ表に対する同じ操作について、複数の文DMLハンドラを使用できます。これらの文DMLハンドラは任意の順序で実行でき、それぞれの文DMLハンドラは元の行LCRを受け取ります。文DMLハンドラによって実行されるSQL操作が失敗するか、EXECUTEメンバー・プロシージャの実行に失敗した場合、その行LCRを含むトランザクションがロールバックされ、適用プロセスのルール・セットに従って適用される必要があるトランザクション内のLCRは、すべてエラー・キューに移動します。

プロシージャDMLハンドラの失敗

プロシージャDMLハンドラによって実行されるSQL操作が失敗するか、EXECUTEメンバー・プロシージャの実行に失敗した場合、プロシージャDMLハンドラは例外処理を試みることができます。プロシージャDMLハンドラが例外を呼び出さなければ、適用プロセスはプロシージャDMLハンドラが行LCRで適切なアクションを実行したものとみなして、適用プロセスのルール・セットに従って適用される必要があるトランザクション内の他のLCRを引き続き適用します。

プロシージャDMLハンドラは、例外を処理できなければ例外を呼び出します。この場合、その行LCRを含むトランザクションがロールバックされ、適用プロセスのルール・セットに従って適用される必要があるトランザクション内のLCRは、すべてエラー・キューに移動します。

DMLハンドラおよび関連する更新の競合ハンドラがある場合

適用プロセスが行LCRをDMLハンドラに渡し、関連する更新の競合ハンドラが構成されている場合を考えます。DMLハンドラは、文DMLハンドラとプロシージャDMLハンドラのどちらでもかまいません。適用プロセスでは、同じ表に対する同じ操作について、複数の文DMLハンドラを使用できます。これらの文DMLハンドラは任意の順序で実行でき、それぞれの文DMLハンドラは元の行LCRを受け取ります。

DMLハンドラによって行LCRが処理されます。DMLハンドラのデザイナがこの処理を全面的に制御します。一部のDMLハンドラは、SQL操作を実行するか、行LCRのEXECUTEメンバー・プロシージャを実行する場合があります。DMLハンドラが行LCRのEXECUTEメンバー・プロシージャを実行すると、適用プロセスは行LCRを適用しようとします。DMLハンドラがプロシージャDMLハンドラである場合、この行LCRはプロシージャDMLハンドラによって変更されている可能性があります。

DMLハンドラによって実行されるSQL操作が失敗するか、更新の競合以外の理由でEXECUTEメンバー・プロシージャの実行に失敗した場合の動作は、「DMLハンドラはあるが関連する更新の競合ハンドラがない場合」で説明した動作と同じです。一意性競合と削除の競合は、更新の競合ではないことに注意してください。

更新の競合が原因でEXECUTEメンバー・プロシージャの実行に失敗した場合の動作は、EXECUTEメンバー・プロシージャのconflict_resolutionパラメータの設定に応じて次のように異なります。

conflict_resolutionパラメータがTRUEに設定されている場合

conflict_resolutionパラメータがTRUEに設定されている場合は、関連する更新の競合ハンドラが起動します。更新の競合ハンドラによって競合が正常に解決され、DMLハンドラによって実行された他のすべての操作が正常終了すると、DMLハンドラは例外を呼び出さずに終了し、適用プロセスはそのルール・セットに従って適用される必要があるトランザクション内の他のLCRを引き続き適用します。

更新の競合ハンドラが競合を解決できず、DMLハンドラが文DMLハンドラである場合、その行LCRを含むトランザクションがロールバックされ、適用プロセスのルール・セットに従って適用される必要があるトランザクション内のLCRは、すべてエラー・キューに移動します。

更新の競合ハンドラが競合を解決できず、DMLハンドラがプロシージャDMLハンドラである場合、プロシージャDMLハンドラは例外処理を試みることができます。プロシージャDMLハンドラが例外を呼び出さなければ、適用プロセスはプロシージャDMLハンドラが行LCRで適切なアクションを実行したものとみなして、適用プロセスのルール・セットに従って適用される必要があるトランザクション内の他のLCRを引き続き適用します。プロシージャDMLハンドラは、例外を処理できなければ例外を呼び出します。この場合、その行LCRを含むトランザクションがロールバックされ、適用プロセスのルール・セットに従って適用される必要があるトランザクション内のLCRは、すべてエラー・キューに移動します。

conflict_resolutionパラメータがFALSEに設定されている場合

conflict_resolutionパラメータがFALSEに設定されている場合、関連する更新の競合ハンドラは起動しません。この場合の動作は、「DMLハンドラはあるが関連する更新の競合ハンドラがない場合」で説明した動作と同じです。

文DMLハンドラおよびプロシージャDMLハンドラがある場合

適用プロセスが行LCRを文DMLハンドラとプロシージャDMLハンドラの両方に渡し、同じ表に対して同じ操作を実行する場合を考えます。この場合、DMLハンドラは任意の順序で実行でき、それぞれのDMLハンドラは元の各行LCRを受け取ります。また、適用プロセスでは、同じ表に対する同じ操作について、複数の文DMLハンドラを使用できます。これらの文DMLハンドラは任意の順序で実行でき、それぞれの文DMLハンドラは元の行LCRを受け取ります。それぞれのDMLハンドラでは行LCRを個別に処理し、その動作はDMLハンドラが関係する他の使用例と同じです。

文DMLハンドラまたはプロシージャDMLハンドラが失敗した場合、その行LCRを含むトランザクションがロールバックされ、適用プロセスのルール・セットに従って適用される必要があるトランザクション内のLCRは、すべてエラー・キューに移動します。

エラー・ハンドラはあるが関連する更新の競合ハンドラがない場合

適用プロセスが行LCRを適用するときにエラーが発生した場合を考えます。このエラーは、競合または他の条件が原因となっている可能性があります。表操作用のエラー・ハンドラはありますが、関連する更新の競合ハンドラは構成されていません。

行LCRがエラー・ハンドラに渡されます。エラー・ハンドラによって行LCRが処理されます。エラー・ハンドラのデザイナがこの処理を全面的に制御します。一部のエラー・ハンドラは、SQL操作を実行するか、行LCRのEXECUTEメンバー・プロシージャを実行する場合があります。エラー・ハンドラが行LCRのEXECUTEメンバー・プロシージャを実行すると、適用プロセスは行LCRを適用しようとします。この行LCRは、エラー・ハンドラによって変更されている可能性があります。

エラー・ハンドラによって実行されるSQL操作が失敗するか、EXECUTEメンバー・プロシージャの実行に失敗した場合、エラー・ハンドラは例外処理を試みることができます。エラー・ハンドラが例外を呼び出さなければ、適用プロセスはエラー・ハンドラが行LCRで適切なアクションを実行したものとみなして、適用プロセスのルール・セットに従って適用される必要があるトランザクション内の他のLCRを引き続き適用します。

エラー・ハンドラは、例外を処理できなければ例外を呼び出します。この場合、その行LCRを含むトランザクションがロールバックされ、適用プロセスのルール・セットに従って適用される必要があるトランザクション内のLCRは、すべてエラー・キューに移動します。

エラー・ハンドラおよび関連する更新の競合ハンドラがある場合

適用プロセスが行LCRを適用するときにエラーが発生した場合を考えます。表操作用のエラー・ハンドラがあり、関連する更新の競合ハンドラが構成されています。

エラー処理のために起動されるハンドラは、次のようにエラーのタイプに応じて異なります。

  • 一意性競合や削除の競合など、更新の競合以外の条件によってエラーが発生すると、エラー・ハンドラが起動します。この場合の動作は、「エラー・ハンドラはあるが関連する更新の競合ハンドラがない場合」で説明した動作と同じです。

  • 更新の競合が原因でエラーが発生すると、更新の競合ハンドラが起動します。更新の競合ハンドラによって競合が正常に解決されると、適用プロセスはそのルール・セットに従って適用される必要があるトランザクション内の他のLCRを引き続き適用します。この場合、エラー・ハンドラは起動しません。

    更新の競合ハンドラが競合を解決できない場合、エラー・ハンドラが起動します。エラー・ハンドラが例外を呼び出さなければ、適用プロセスはエラー・ハンドラが行LCRで適切なアクションを実行したものとみなして、適用プロセスのルール・セットに従って適用される必要があるトランザクション内の他のLCRを引き続き適用します。エラー・ハンドラは、LCRを処理できなければ例外を呼び出します。この場合、その行LCRを含むトランザクションがロールバックされ、適用プロセスのルール・セットに従って適用される必要があるトランザクション内のLCRは、すべてエラー・キューに移動します。

文DMLハンドラおよび関連するエラー・ハンドラがある場合

適用プロセスが行LCRを文DMLハンドラに渡し、関連するエラー・ハンドラが構成されている場合を考えます。

文DMLハンドラによって行LCRが処理されます。文DMLハンドラのデザイナがこの処理を全面的に制御します。一部の文DMLハンドラは、SQL操作を実行するか、行LCRのEXECUTEメンバー・プロシージャを実行する場合があります。文DMLハンドラが行LCRのEXECUTEメンバー・プロシージャを実行すると、適用プロセスは行LCRを適用しようとします。

また、適用プロセスでは、同じ表に対する同じ操作について、複数の文DMLハンドラを使用できます。これらの文DMLハンドラは任意の順序で実行でき、それぞれの文DMLハンドラは元の行LCRを受け取ります。

文DMLハンドラによって実行されるSQL操作が失敗するか、なんらかの理由でEXECUTEメンバー・プロシージャの実行に失敗した場合の動作は、「エラー・ハンドラはあるが関連する更新の競合ハンドラがない場合」で説明した動作と同じです。エラー・ハンドラは、文DMLハンドラによって処理された行LCRではなく、元の行LCRを取得します。


注意:

プロシージャDMLハンドラとエラー・ハンドラを同時に使用して、同じ表に対して同じ操作を実行することはできません。したがって、両方のハンドラが起動される使用例はありません。

文DMLハンドラ、エラー・ハンドラおよび関連する更新の競合ハンドラがある場合

適用プロセスが行LCRを文DMLハンドラに渡し、関連するエラー・ハンドラと更新の競合ハンドラが構成されている場合を考えます。

文DMLハンドラによって行LCRが処理されます。文DMLハンドラのデザイナがこの処理を全面的に制御します。一部の文DMLハンドラは、SQL操作を実行するか、行LCRのEXECUTEメンバー・プロシージャを実行する場合があります。文DMLハンドラが行LCRのEXECUTEメンバー・プロシージャを実行すると、適用プロセスは行LCRを適用しようとします。

また、適用プロセスでは、同じ表に対する同じ操作について、複数の文DMLハンドラを使用できます。これらの文DMLハンドラは任意の順序で実行でき、それぞれの文DMLハンドラは元の行LCRを受け取ります。

文DMLハンドラによって実行されるSQL操作が失敗するか、なんらかの理由でEXECUTEメンバー・プロシージャの実行に失敗した場合の動作は、「エラー・ハンドラおよび関連する更新の競合ハンドラがある場合」で説明した動作と同じです。


注意:

プロシージャDMLハンドラとエラー・ハンドラを同時に使用して、同じ表に対して同じ操作を実行することはできません。したがって、両方のハンドラが起動される使用例はありません。

DDL変更を適用するときの考慮事項

次の各項では、表にDDL変更を適用するときの考慮事項について説明します。

システム生成名

ソース・データベースでDDL変更を取得して、それを宛先データベースで適用する予定の場合は、システム生成名を使用しないでください。DDL文の結果としてオブジェクト名がシステムによって生成される場合、通常、オブジェクト名はソース・データベースとそこからのDDL変更を適用する各宛先データベースで異なるものになります。オブジェクト名が異なると、将来のDDL変更に適用エラーが発生する可能性があります。

たとえば、ソース・データベースで次のDDL文を実行する場合を考えます。

CREATE TABLE sys_gen_name (n1 NUMBER  NOT NULL); 

この文の結果、システム生成名を持つNOT NULL制約が作成されます。たとえば、NOT NULL制約の名前がsys_001500であるとします。この変更が宛先データベースで適用されると、この制約のシステム生成名がsys_c1000となる場合があります。

ソース・データベースで次のDDL文を実行する場合を考えます。

ALTER TABLE sys_gen_name DROP CONSTRAINT sys_001500;

このDDL文は、ソース・データベースでは成功しますが、宛先データベースでは失敗し、適用エラーになります。

この種のエラーを回避するには、DDL文によって作成されるすべてのオブジェクトの名前を明示的に指定します。たとえば、NOT NULL制約の名前を明示的に指定するには、次のDDL文を実行します。

CREATE TABLE sys_gen_name (n1 NUMBER CONSTRAINT sys_gen_name_nn NOT NULL);

CREATE TABLE AS SELECT文

CREATE TABLE AS SELECT文から発生した変更を適用する場合、適用プロセスでは次の2つの手順が実行されます。

  1. CREATE TABLE AS SELECT文が宛先データベースで実行されますが、表の構造のみが作成されます。表に行は挿入されません。CREATE TABLE AS SELECT文が失敗すると、適用プロセスがエラーになります。それ以外の場合は、文が自動コミットされ、適用プロセスによって手順2が実行されます。

  2. 適用プロセスによって、CREATE TABLE AS SELECT文の結果としてソース・データベースで挿入された行が、宛先データベースで対応する表に挿入されます。取得プロセス、伝播または適用プロセスでは、これらの挿入を伴うすべての行LCRが、それぞれのルール・セットに基づいて廃棄される場合があります。この場合、宛先データベースでは表が空のままになります。

DDL文内のDML文

適用プロセスによってデータ定義言語(DDL)の変更が適用されるとき、Oracle Streamsでは同じトランザクション内のDDLターゲットに対するデータ操作言語(DML)の変更は宛先データベースに絶対にレプリケートされません。したがって、ソース・データベースと宛先データベースに相違が生じる場合があります。行論理変更レコード(LCR)の古い値が宛先の表の現在の値と一致しないと、相違によって適用プロセス・エラーが発生する可能性があります。

次の場合、ソース・データベースと宛先データベースに相違が生じます。

DDL文に導出値が含まれている場合

DDL文に導出される非リテラル値が含まれている場合、導出される値はソース・データベースと宛先データベースで一致しない可能性があります。たとえば、次のDDL文を実行すると、hr.employees表に1列が追加され、ソース・データベースを実行しているコンピュータ・システムから導出される日付値が挿入されます。

ALTER TABLE hr.employees ADD(start_date DATE DEFAULT SYSDATE);

レプリケーション環境においてソース・データベースと宛先データベースの間でhr.employees表に対するDML変更とDDL変更が維持されると想定します。この場合、SYSDATEファンクションはソース・データベースと宛先データベースで個別に実行されます。したがって、ソース・データベースで挿入されるDATE値は、宛先データベースで挿入されるDATE値と一致しません。

DDL文によってDMLトリガーが起動される場合

DDL文によって、宛先の表で定義されたDMLトリガーが起動される場合、トリガーによって行われるDML変更は宛先データベースでレプリケートされません。トリガーによるDML変更はDDL文と同じトランザクションで行われ、DDL文のターゲットである表に影響するため、トリガーされるDML変更は宛先データベースでレプリケートされません。

たとえば、次の表を作成するものとします。

CREATE TABLE hr.temp_employees(
   emp_id       NUMBER  PRIMARY KEY,
   first_name   VARCHAR2(64),
   last_name    VARCHAR2(64),
   modify_date  TIMESTAMP);

表でトリガーを作成し、表が更新されるたびにmodify_date列を更新して変更時間を反映するようにするとします。

CREATE OR REPLACE TRIGGER hr.trg_mod_dt BEFORE UPDATE ON hr.temp_employees
   REFERENCING
   NEW AS NEW_ROW FOR EACH ROW
BEGIN
   :NEW_ROW.modify_date:= SYSTIMESTAMP;
END;
/

レプリケーション環境においてソース・データベースと宛先データベースの間でhr.temp_employees表に対するDML変更とDDL変更が維持されると想定します。この場合、ソース・データベースでhr.temp_employees表に対して直接行われるDML変更にあわせて、宛先データベースでもこの表は正しく維持されます。ただし、ソース・データベースのADD COLUMN文によってこの表に列が追加される場合、hr.trg_mod_dt更新トリガーによって表のすべての行のmodify_date列が新しいタイムスタンプに変更されます。modify_date列に対するこれらの変更は宛先データベースでレプリケートされません。

適用プロセスのインスタンス化SCNと非処理SCN

1つのデータベース内または複数のデータベース間で情報を共有するOracle Streams環境の場合、ソース・データベースとはREDOログ内で変更が生成されるデータベースです。次の特性を持つ環境を考えます。

  • 取得プロセスまたは同期取得は、ソース・データベースの表に対する変更を取得し、変更をLCRとしてキューにステージングします。

  • 適用プロセスは、同じデータベースまたはLCRが伝播された宛先データベースのどちらかで、これらのLCRを適用します。

このような環境では、表ごとに、ソース・データベースで特定のシステム変更番号(SCN)の後にコミットされた変更のみが適用されます。インスタンス化SCNは、各表でこの値を指定します。

インスタンス化SCNは、インスタンス化時に設定するか、またはDBMS_APPLY_ADMパッケージのプロシージャを使用して設定できます。Oracle Streamsレプリケーション環境が構成される前に表が宛先データベースに存在しない場合、ソース・データベースからのコピーを使用して、表が物理的に作成(インスタンス化)され、インスタンス化SCNがインスタンス化時に各表に設定されます。Oracle Streamsレプリケーション環境が構成される前に表が宛先データベースにすでに存在する場合、ソース・データベースからのコピーを使用した表のインスタンス化は行われません。かわりに、DBMS_APPLY_ADMパッケージに含まれるSET_TABLE_INSTANTIATION_SCNSET_SCHEMA_INSTANATIATION_SCNまたはSET_GLOBAL_INSTANTIATION_SCNプロシージャのいずれかを使用して、表ごとに手動でインスタンス化SCNを設定する必要があります。

データベース・オブジェクトのインスタンス化SCNによって、データベース・オブジェクトに対する変更を含むLCRのうち、適用プロセスで無視されるLCRと適用されるLCRが制御されます。ソース・データベースからのデータベース・オブジェクトに関するLCRのコミットSCNが、宛先データベースでそのデータベース・オブジェクトのインスタンス化SCN以下であれば、宛先データベースの適用プロセスではLCRが廃棄されます。それ以外の場合は、適用プロセスによってLCRが適用されます。

また、宛先データベースの共有データベース・オブジェクトに対して複数のソース・データベースがある場合は、ソース・データベースごとにインスタンス化SCNを設定する必要があります。このインスタンス化SCNは、ソース・データベースごとに異なっていてもかまいません。エクスポート/インポートまたはトランスポータブル表領域を使用して、インスタンス化SCNを設定できます。また、DBMS_APPLY_ADMパッケージのプロシージャを使用して、インスタンス化SCNを設定することもできます。

また、Oracle Streamsでは各データベース・オブジェクトについて非処理SCNが記録されます。非処理SCNは、その下にデータベース・オブジェクトに対する変更を適用できないSCNです。オブジェクトのインスタンス化SCNは、オブジェクトの非処理SCNの下には設定できません。この値は、オブジェクトがインスタンス化のために準備された時点でのソース・データベースのSCN値に相当します。非処理SCNは、Oracle Data Pumpを使用してデータベース・オブジェクトがインスタンス化された場合にのみ、データベース・オブジェクトに設定されます。

データベース・オブジェクトのインスタンス化SCNおよび非処理SCNを表示するには、DBA_APPLY_INSTANTIATED_OBJECTSデータ・ディクショナリ・ビューを問い合せます。


関連項目:

『Oracle Streamsレプリケーション管理者ガイド』

適用プロセスの最も古いSCN

適用プロセスが実行されている場合、最も古いSCNは、現在デキューおよび適用されているトランザクションの最も若いSCNです。停止した適用プロセスの場合、最も古いSCNは、適用プロセスが停止した際に適用されていたトランザクションの最も若いSCNです。

最も古いSCNが重要になるのは、次の2つの一般的な使用例の場合です。

  • 適用プロセスを実行中のデータベースを特定の時点までリカバリする必要がある場合。

  • 適用プロセス用の変更を取得するために、既存の取得プロセスの使用を停止し、別の取得プロセスを使用する場合。

どちらの場合も、DBA_APPLY_PROGRESSデータ・ディクショナリ・ビューを問い合せて、適用プロセス用の最も古いSCNを判別する必要があります。このビューのOLDEST_MESSAGE_NUMBER列に、最も古いSCNが含まれています。次に、適用プロセス用の変更を取得する取得プロセスの開始SCNを、最も古いSCNと同じ値に設定します。取得プロセスが他の適用プロセス用の変更を取得している場合は、取得プロセスの開始SCNをリセットすると、これらの他の適用プロセスは重複するLCRを受け取ることがあります。この場合、これらの適用プロセスでは重複するLCRが自動的に廃棄されます。


注意:

最も古いSCNは、取得プロセスで取得されたLCRを適用する適用プロセスに対してのみ有効です。同期取得で取得されたLCRまたは明示的にエンキューされたLCRを適用する適用プロセスには関連していません。


関連項目:


適用プロセスの最低水位標と最高水位標

適用プロセスの最低水位標は、すべてのLCRが適用済となっている最大のシステム変更番号(SCN)です。つまり、最低水位標番号以下のSCNでコミットされたLCRは確実に適用されていますが、それを超えるSCNでコミットされた一部のLCRも適用されている可能性があります。適用プロセスの最低水位標SCNは、取得プロセスの適用済SCNと等価です。

適用プロセスの最高水位標は、その番号を超えて適用されたLCRのないSCNです。つまり、最高水位標を超えるSCNでコミットされたLCRは適用されていません。

1つ以上の適用プロセスについて最低水位標と最高水位標を表示するには、V$STREAMS_APPLY_COORDINATORおよびALL_APPLY_PROGRESSデータ・ディクショナリ・ビューを問い合せます。

適用プロセスおよびトリガー

この項では、Oracle Streamsの適用プロセスとトリガーの対話の仕組みについて説明します。

この項の内容は次のとおりです。


関連項目:


トリガー起動プロパティ

DBMS_DDLパッケージのSET_TRIGGER_FIRING_PROPERTYプロシージャを使用すると、DMLまたはDDLトリガーの起動プロパティを制御できます。このプロシージャでは、トリガーを常に起動するか、1回起動するか、または適用プロセスによって変更が行われる場合にのみ起動するかを指定できます。

SET_TRIGGER_FIRING_PROPERTYプロシージャはオーバーロードされます。トリガーの起動プロパティは、次のいずれかの方法で設定します。

  • トリガーを常に起動するように指定するには、fire_onceプロシージャ・パラメータをFALSEに設定します。

  • トリガーを1回起動するように指定するには、fire_onceプロシージャ・パラメータをTRUEに設定します。

  • 適用プロセスによって変更が行われる場合にのみトリガーを起動するように指定するには、propertyパラメータをDBMS_DDL.APPLY_SERVER_ONLYに設定します。

トリガーに対してDBMS_DDL.APPLY_SERVER_ONLYプロパティを設定すると、fire_onceパラメータの設定に関係なく、適用プロセスによって変更が行われる場合にのみトリガーが起動します。つまり、propertyパラメータに対してDBMS_DDL.APPLY_SERVER_ONLYを設定した場合、fire_onceパラメータの設定よりも優先されます。

トリガーの起動プロパティによって、次のそれぞれの状況でトリガーが起動するかどうかが決まります。

  • ユーザー・プロセスによってトリガー・イベントが実行された場合

  • 適用プロセスによってトリガー・イベントが実行された場合

  • DBMS_APPLY_ADMパッケージのEXECUTE_ERRORまたはEXECUTE_ALL_ERRORSプロシージャを使用して1つ以上の適用エラーを実行した結果としてトリガー・イベントが発生した場合

表10-2に、トリガー起動プロパティに基づくトリガーの起動有無を示します。

表10-2 トリガー起動プロパティ

トリガー起動プロパティ ユーザー・プロセスによってトリガー・イベントが発生した場合 適用プロセスによってトリガー・イベントが発生した場合 適用エラーの実行によってトリガー・イベントが発生した場合

常に起動

トリガーは起動する

トリガーは起動する

トリガーは起動する

1回起動

トリガーは起動する

トリガーは起動しない

トリガーは起動しない

適用プロセスによって変更が行われる場合のみ

トリガーは起動しない

トリガーは起動する

トリガーは起動する


たとえば、hrスキーマ内で、employees表のjob_id列またはdepartment_id列のデータが更新されると、update_job_historyトリガーによってjob_history表に1行が追加されます。この場合、Oracle Streams環境に次の構成が存在すると考えます。

  • 取得プロセスまたは同期取得は、dbs1.example.comデータベースでこの2つの表に対する変更を取得します。

  • 伝播は、これらの変更をdbs2.example.comデータベースに伝播させます。

  • 適用プロセスは、これらの変更をdbs2.example.comデータベースで適用します。

  • どちらのデータベースでも、hrスキーマにupdate_job_historyトリガーが存在します。

この使用例で、update_job_historyトリガーがdbs2.example.comで常に起動するように設定されていれば、これらのアクションの結果は次のようになります。

  1. dbs1.example.comで、employees表の従業員に関するjob_id列が更新されます。

  2. dbs1.example.comupdate_job_historyトリガーが起動し、変更を記録するjob_history表に1行が追加されます。

  3. dbs1.example.comの取得プロセスまたは同期取得は、employees表とjob_history表の両方に対する変更を取得します。

  4. 伝播は、これらの変更をdbs2.example.comデータベースに伝播させます。

  5. dbs2.example.comデータベースの適用プロセスは、両方の変更を適用します。

  6. 適用プロセスによってemployees表が更新されると、dbs2.example.comupdate_job_historyトリガーが起動します。

この場合、employees表に対する変更は、dbs2.example.comデータベースで2回記録されます。1回は適用プロセスが変更をjob_history表に適用する時点で、もう1回はupdate_job_historyトリガーが起動して、適用プロセスによってemployees表に対して行われた変更を記録する時点です。

データベース管理者は、適用プロセスによって変更が行われるときに、dbs2.example.comデータベースでupdate_job_historyトリガーが起動しないようにする必要がある場合があります。同様に、データベース管理者は、適用エラー・トランザクションの実行が原因でトリガーが起動しないようにする必要がある場合もあります。update_job_historyトリガーの起動プロパティを1回起動するように設定すると、適用プロセスによって変更がemployees表に適用されるときにも、実行されたエラー・トランザクションによってemployees表が更新されるときにも、dbs2.example.comでトリガーは起動しません。


注意:

1回起動するように設定できるのは、DMLトリガーとDDLトリガーのみです。他のタイプのトリガーは、すべて常に起動します。


関連項目:

SET_TRIGGER_FIRING_PROPERTYプロシージャを使用してトリガーの起動プロパティを設定する方法の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照

適用プロセスとON SCHEMA句で作成したトリガー

ON SCHEMA句を使用してスキーマ・トリガーを作成した場合、そのスキーマ・トリガーは、スキーマにより関連する変更が実行される場合にのみ起動します。したがって、適用プロセスにより変更が適用されるときには、常に起動するように設定されたスキーマ・トリガーは、適用ユーザーがスキーマ・トリガーで指定されたスキーマと同じ場合にのみ起動します。スキーマ・トリガーが1回起動するように設定されている場合は、適用ユーザーがスキーマ・トリガーで指定されたスキーマと同じかどうかにかかわらず、適用プロセスでの変更適用時にトリガーは起動しません。

たとえば、ソース・データベースおよび宛先データベースのhrスキーマで常に起動するスキーマ・トリガーを指定した場合に、宛先データベースの適用ユーザーがstrmadminであれば、hrユーザーがソース・データベースで関連する変更を実行するときにはトリガーが起動しますが、この変更が宛先データベースで適用されるときにはトリガーは起動しません。ただし、宛先データベースのstrmadminスキーマで常に起動するスキーマ・トリガーを指定した場合は、ソース・データベースのトリガー仕様にかかわらず、適用プロセスにより関連する変更が行われるときに必ずこのトリガーが起動します。

適用プロセス用のOracle Streamsデータ・ディクショナリ

ソース・データベースでデータベース・オブジェクトのインスタンス化が準備されている場合、オブジェクトに対する変更が取得プロセスによって取得されるデータベースで、Oracle Streamsデータ・ディクショナリが自動的に移入されます。Oracle Streamsデータ・ディクショナリは、ソース・データベースのプライマリ・データ・ディクショナリ内の一部の情報のマルチバージョン・コピーです。Oracle Streamsデータ・ディクショナリでは、ソース・データベースのオブジェクト番号、オブジェクト・バージョン情報および内部列番号が表名、列名および列のデータ型にマップされます。取得LCRでは名前ではなく番号を内部的に使用できるため、このマッピングによって、各取得LCRのサイズが最小に保たれます。

取得または伝播時に取得LCRがパラメータとしてカスタム・ルールベースの変換に渡される場合を除き、取得LCRを適用するすべてのデータベースで、LCRの内容の解釈にソース・データベースのOracle Streamsデータ・ディクショナリのマッピング情報が必要となります。適用プロセスでこのマッピング情報を使用できるようにするために、Oracle Streams適用プロセスを持つ各宛先データベースで、マルチバージョンOracle Streamsデータ・ディクショナリが自動的に移入されます。ソース・データベースのOracle Streamsデータ・ディクショナリから、ソース・データベースからの取得LCRを適用するその他すべてのデータベースに、関連情報が自動的に伝播されます。

単一データベースでの複数の適用プロセス

単一データベースで複数の適用プロセスを実行する場合は、システム・グローバル領域(SGA)のサイズを増やすことを検討してください。SGAサイズを増やすには、SGA_MAX_SIZE初期化パラメータを使用します。また、Oracle Streamsプールのサイズがデータベースで自動管理されていない場合は、適用プロセスの並列性ごとにOracle Streamsプールを 1MB増やす必要があります。たとえば、2つの適用プロセスがデータベースで実行されており、parallelismパラメータが一方の適用プロセスでは4、もう一方の適用プロセスでは1に設定されている場合、Oracle Streamsプールを5MB(並列性は4+1=5)増やします。


注意:

MEMORY_TARGETMEMORY_MAX_TARGETまたはSGA_TARGET初期化パラメータが0(ゼロ)以外の値に設定されている場合、Oracle Streamsプールのサイズは自動的に管理されます。


関連項目:

  • Oracle Streamsプールの詳細は、『Oracle Streamsレプリケーション管理者ガイド』を参照

  • STREAMS_POOL_SIZE初期化パラメータの詳細は、『Oracle Streamsレプリケーション管理者ガイド』を参照