ヘッダーをスキップ
Oracle Streamsレプリケーション管理者ガイド
11g リリース1(11.1)
E05776-02
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

21 n-wayレプリケーションの例

この章では、Oracle Streamsを使用して構成できるn-wayレプリケーション環境の例を説明します。

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

n-wayレプリケーション例の概要

この例では、Oracle Streamsを使用して、3つのOracle Database間でスキーマのデータをレプリケートする方法について説明します。hrmultスキーマ内の表に対するDML変更とDDL変更が、この環境の全データベースで取得され、この環境の他の各データベースに伝播します。

この種の環境は、n-wayレプリケーション環境と呼ばれます。n-wayレプリケーション環境は、複数のソース・データベースで変更が取得およびレプリケートされる、複数ソース・レプリケーション環境の一種です。

図21-1に、この環境の概要を示します。

図21-1 n-wayレプリケーション環境の例

図21-1の説明が続きます。
図21-1「n-wayレプリケーション環境の例」の説明

図21-1に示すように、この例が完了すると、すべてのデータベースにhrmultスキーマが含まれることになります。ただし、この例の開始時には、hrmultスキーマはmult1.netにのみ存在します。この例の実行中に、mult2.netmult3.nethrmultスキーマをインスタンス化します。

この例では、Oracle Streamsを使用して次の一連のアクションが実行されます。

  1. インスタンス化の後に、各データベースの取得プロセスが、hrmultスキーマ内のすべての表に対するDML変更とDDL変更を取得し、それをローカル・キューにエンキューします。

  2. 各データベースの伝播が、これらの変更を環境内の他の全データベースに伝播します。

  3. 各データベースの適用プロセスが、環境内の他のデータベースから受信したhrmultスキーマ内の変更を適用します。

この例では、適用プロセスにデフォルトの適用タグを使用して、変更がソース・データベースに送信されるのを回避します。適用プロセスを作成すると、その適用プロセスで適用される変更のREDOエントリには、デフォルトでタグ'00'(2つのゼロ)が使用されます。デフォルトでは、これらの変更が再取得されることはありません。これは、DBMS_STREAMS_ADMパッケージで作成されたルールにはデフォルトでis_null_tag()='Y'条件があり、この条件によって、REDOエントリのタグがNULLの場合にのみ各取得プロセスでREDOエントリに対する変更が確実に取得されるためです。


参照:


前提条件

この章の例を開始する前に、前提条件となる次の作業を完了する必要があります。

mult1.netデータベースでのhrmultスキーマの作成

この例のために、mult1.netデータベースにhrmultという新しいスキーマを作成します。n-way環境では、この新しいスキーマがレプリケートされます。

次の手順を実行して、データ・ポンプ・エクスポート/インポートを使用し、hrスキーマのコピーであるhrmultスキーマを作成します。

  1. SQL*Plusで、管理ユーザーとしてmult1.netデータベースに接続します。

    SQL*Plusでデータベースに接続する手順については、『Oracle Database管理者ガイド』を参照してください。

  2. エクスポート・ダンプ・ファイルおよびエクスポート・ログ・ファイルを保持するディレクトリ・オブジェクトを作成します。このディレクトリ・オブジェクトは、コンピュータ・システム上のアクセス可能な任意のディレクトリを指すことができます。たとえば、次の文を実行すると、/usr/tmpディレクトリを指すディレクトリ・オブジェクトdp_hrmult_dirが作成されます。

    CREATE DIRECTORY dp_hrmult_dir AS '/usr/tmp';
    

    コンピュータ・システム上の適切なディレクトリに置き換えてください。

  3. ソース・データベースの現行のシステム変更番号(SCN)を判別します。

    SELECT DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER FROM DUAL;
    

    この問合せで戻されるSCN値を、手順5FLASHBACK_SCNデータ・ポンプ・エクスポート・パラメータに指定します。hrスキーマには表間の外部キー制約が含まれるため、FLASHBACK_SCNエクスポート・パラメータ、または類似のエクスポート・パラメータは、エクスポート中に指定する必要があります。

  4. SQL*Plusを終了します。

  5. mult1.netデータベース・サイトのコマンドラインでデータ・ポンプを使用して、mult1.netデータベースのhrスキーマをエクスポートします。手順3で戻されたSCN値をFLASHBACK_SCNパラメータに指定してください。

    expdp system SCHEMAS=hr DIRECTORY=dp_hrmult_dir
    DUMPFILE=hrmult_schema.dmp FLASHBACK_SCN=flashback_scn_value
    
  6. mult1.netデータベース・サイトのコマンドラインでデータ・ポンプを使用して、インポート・ダンプ・ファイルhrmult_schema.dmpをインポートします。

    impdp system SCHEMAS=hr DIRECTORY=dp_hrmult_dir
    DUMPFILE=hrmult_schema.dmp REMAP_SCHEMA=hr:hrmult
    
  7. SQL*Plusで、管理ユーザーとしてmult1.netデータベースに接続します。

  8. ALTER USER文を使用して、mult1.netデータベースの新しいユーザーhrmultにパスワードを割り当てます。

    将来hrmultユーザーとしてログインできるように、割り当てたパスワードを覚えておいてください。

キューおよびデータベース・リンクの作成

この項では、3つのOracle Databaseを含むOracle Streamsレプリケーション環境にキューおよびデータベース・リンクを作成する方法について説明します。この章の残りの項は、この項で構成するキューおよびデータベース・リンクによって異なります。

次の手順を実行して、すべてのデータベースでキューおよびデータベース・リンクを作成します。

  1. 出力およびスプール結果の表示

  2. mult1.netでのANYDATAキューの作成

  3. mult1.netでのデータベース・リンクの作成

  4. mult1.netでの最新時刻に基づいた競合解消のための表の準備

  5. mult2.netでのANYDATAキューの作成

  6. mult2.netでのデータベース・リンクの作成

  7. mult3.netでのANYDATAキューの作成

  8. mult3.netでのデータベース・リンクの作成

  9. スプール結果のチェック


注意:

このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL streams_setup_mult.out

/*

手順2: mult1.netでのANYDATAキューの作成

Oracle Streams管理者としてmult1.netに接続します。

*/

CONNECT strmadmin@mult1.net

/*

SET_UP_QUEUEプロシージャを実行して、次のキューを作成します。

SET_UP_QUEUEプロシージャを実行すると、各キューに次のアクションが実行されます。

*/

BEGIN
  DBMS_STREAMS_ADM.SET_UP_QUEUE(
    queue_table  => 'strmadmin.captured_mult1_table',
    queue_name   => 'strmadmin.captured_mult1');
END;
/

BEGIN
  DBMS_STREAMS_ADM.SET_UP_QUEUE(
    queue_table  => 'strmadmin.from_mult2_table',
    queue_name   => 'strmadmin.from_mult2');
END;
/

BEGIN
  DBMS_STREAMS_ADM.SET_UP_QUEUE(
    queue_table  => 'strmadmin.from_mult3_table',
    queue_name   => 'strmadmin.from_mult3');
END;
/

/*

手順3: mult1.netでのデータベース・リンクの作成

現行データベースから環境内の他のデータベースへのデータベース・リンクを作成します。

*/

ACCEPT password PROMPT 'Enter password for user: ' HIDE

CREATE DATABASE LINK mult2.net CONNECT TO strmadmin
   IDENTIFIED BY &password USING 'mult2.net';

CREATE DATABASE LINK mult3.net CONNECT TO strmadmin
   IDENTIFIED BY &password USING 'mult3.net';

/*

手順4: mult1.netでの最新時刻に基づいた競合解消のための表の準備

この例では、トランザクションの最新時刻に基づいて競合解消が行われるようにhrmultスキーマ内の表を構成します。

hrmultユーザーとしてmult1.netに接続します。

*/

CONNECT hrmult@mult1.net

/*

hrmultスキーマ内の各表にtime列を追加します。

*/

ALTER TABLE hrmult.countries ADD (time TIMESTAMP WITH TIME ZONE);
ALTER TABLE hrmult.departments ADD (time TIMESTAMP WITH TIME ZONE);
ALTER TABLE hrmult.employees ADD (time TIMESTAMP WITH TIME ZONE);
ALTER TABLE hrmult.job_history ADD (time TIMESTAMP WITH TIME ZONE);
ALTER TABLE hrmult.jobs ADD (time TIMESTAMP WITH TIME ZONE);
ALTER TABLE hrmult.locations ADD (time TIMESTAMP WITH TIME ZONE);
ALTER TABLE hrmult.regions ADD (time TIMESTAMP WITH TIME ZONE);

/*

hrmultスキーマ内の各表用のトリガーを作成し、トランザクションによって挿入または更新された各行のトランザクションの時刻を挿入します。

*/

CREATE OR REPLACE TRIGGER hrmult.insert_time_countries
BEFORE
  INSERT OR UPDATE ON hrmult.countries 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;
/

CREATE OR REPLACE TRIGGER hrmult.insert_time_departments
BEFORE
  INSERT OR UPDATE ON hrmult.departments FOR EACH ROW
BEGIN
   IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
     :NEW.TIME := SYSTIMESTAMP;
   ELSE
     :NEW.TIME := :OLD.TIME + 1 / 86400;
   END IF;
END;
/

CREATE OR REPLACE TRIGGER hrmult.insert_time_employees
BEFORE
  INSERT OR UPDATE ON hrmult.employees FOR EACH ROW
BEGIN
   IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
     :NEW.TIME := SYSTIMESTAMP;
   ELSE
     :NEW.TIME := :OLD.TIME + 1 / 86400;
   END IF;
END;
/

CREATE OR REPLACE TRIGGER hrmult.insert_time_job_history
BEFORE
  INSERT OR UPDATE ON hrmult.job_history FOR EACH ROW
BEGIN
   IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
     :NEW.TIME := SYSTIMESTAMP;
   ELSE
     :NEW.TIME := :OLD.TIME + 1 / 86400;
   END IF;
END;
/

CREATE OR REPLACE TRIGGER hrmult.insert_time_jobs
BEFORE
  INSERT OR UPDATE ON hrmult.jobs FOR EACH ROW
BEGIN
   IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
     :NEW.TIME := SYSTIMESTAMP;
   ELSE
     :NEW.TIME := :OLD.TIME + 1 / 86400;
   END IF;
END;
/

CREATE OR REPLACE TRIGGER hrmult.insert_time_locations
BEFORE
  INSERT OR UPDATE ON hrmult.locations FOR EACH ROW
BEGIN
   IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
     :NEW.TIME := SYSTIMESTAMP;
   ELSE
     :NEW.TIME := :OLD.TIME + 1 / 86400;
   END IF;
END;
/

CREATE OR REPLACE TRIGGER hrmult.insert_time_regions
BEFORE
  INSERT OR UPDATE ON hrmult.regions FOR EACH ROW
BEGIN
   IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
     :NEW.TIME := SYSTIMESTAMP;
   ELSE
     :NEW.TIME := :OLD.TIME + 1 / 86400;
   END IF;
END;
/

/*

手順5: mult2.netでのANYDATAキューの作成

Oracle Streams管理者としてmult2.netに接続します。

*/

CONNECT strmadmin@mult2.net

/*

SET_UP_QUEUEプロシージャを実行して、次のキューを作成します。

SET_UP_QUEUEプロシージャを実行すると、各キューに次のアクションが実行されます。

*/

BEGIN
  DBMS_STREAMS_ADM.SET_UP_QUEUE(
    queue_table  => 'strmadmin.captured_mult2_table',
    queue_name   => 'strmadmin.captured_mult2');
END;
/

BEGIN
  DBMS_STREAMS_ADM.SET_UP_QUEUE(
    queue_table  => 'strmadmin.from_mult1_table',
    queue_name   => 'strmadmin.from_mult1');
END;
/

BEGIN
  DBMS_STREAMS_ADM.SET_UP_QUEUE(
    queue_table  => 'strmadmin.from_mult3_table',
    queue_name   => 'strmadmin.from_mult3');
END;
/

/*

手順6: mult2.netでのデータベース・リンクの作成

現行データベースから環境内の他のデータベースへのデータベース・リンクを作成します。

*/

CREATE DATABASE LINK mult1.net CONNECT TO strmadmin
   IDENTIFIED BY &password USING 'mult1.net';

CREATE DATABASE LINK mult3.net CONNECT TO strmadmin
   IDENTIFIED BY &password USING 'mult3.net';

/*

手順7: mult3.netでのANYDATAキューの作成

Oracle Streams管理者としてmult3.netに接続します。

*/

CONNECT strmadmin@mult3.net

/*

SET_UP_QUEUEプロシージャを実行して、次のキューを作成します。

SET_UP_QUEUEプロシージャを実行すると、各キューに次のアクションが実行されます。

*/

BEGIN
  DBMS_STREAMS_ADM.SET_UP_QUEUE(
    queue_table  => 'strmadmin.captured_mult3_table',
    queue_name   => 'strmadmin.captured_mult3');
END;
/

BEGIN
  DBMS_STREAMS_ADM.SET_UP_QUEUE(
    queue_table  => 'strmadmin.from_mult1_table',
    queue_name   => 'strmadmin.from_mult1');
END;
/

BEGIN
  DBMS_STREAMS_ADM.SET_UP_QUEUE(
    queue_table  => 'strmadmin.from_mult2_table',
    queue_name   => 'strmadmin.from_mult2');
END;
/

/*

手順8: mult3.netでのデータベース・リンクの作成

現行データベースから環境内の他のデータベースへのデータベース・リンクを作成します。

*/

CREATE DATABASE LINK mult1.net CONNECT TO strmadmin
   IDENTIFIED BY &password USING 'mult1.net';

CREATE DATABASE LINK mult2.net CONNECT TO strmadmin
   IDENTIFIED BY &password USING 'mult2.net';

/*

手順9: スプール結果のチェック

streams_setup_mult.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

n-wayレプリケーションを構成するスクリプトの例

次の手順を実行して、Oracle Streams n-wayレプリケーション環境を構成します。

  1. 出力およびスプール結果の表示

  2. mult1.netでのサプリメンタル・ロギングの指定

  3. mult1.netでの取得プロセスの作成

  4. mult1.netでの各ソース・データベース用の1つの適用プロセスの作成

  5. mult1.netでの最新時刻に基づいた競合解消の構成

  6. mult1.netでの伝播の構成

  7. mult2.netでの取得プロセスの作成

  8. 他のデータベースでのmult2.netに対するインスタンス化SCNの設定

  9. mult2.netでの各ソース・データベース用の1つの適用プロセスの作成

  10. mult2.netでの伝播の構成

  11. mult3.netでの取得プロセスの作成

  12. 他のデータベースでのmult3.netに対するインスタンス化SCNの設定

  13. mult3.netでの各ソース・データベース用の1つの適用プロセスの作成

  14. mult3.netでの伝播の構成

  15. mult2.netでのhrmultスキーマのインスタンス化

  16. mult3.netでのhrmultスキーマのインスタンス化

  17. mult2.netでの最新時刻に基づいた競合解消の構成

  18. mult2.netでの適用プロセスの起動

  19. mult3.netでの最新時刻に基づいた競合解消の構成

  20. mult3.netでの適用プロセスの起動

  21. mult1.netでの適用プロセスの起動

  22. mult1.netでの取得プロセスの起動

  23. mult2.netでの取得プロセスの起動

  24. mult3.netでの取得プロセスの起動

  25. スプール結果のチェック


注意:

このマニュアルをオンラインで参照している場合、この注意の後にある「BEGINNING OF SCRIPT」の行から次の「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーし、テキストを編集してご使用の環境用のスクリプトを作成できます。環境内のすべてのデータベースに接続可能なコンピュータで、SQL*Plusを使用してスクリプトを実行します。

/************************* BEGINNING OF SCRIPT ******************************

手順1: 出力およびスプール結果の表示

SET ECHO ONを実行し、スクリプトのスプール・ファイルを指定します。このスクリプトの実行後に、スプール・ファイルにエラーがないかをチェックします。

*/

SET ECHO ON
SPOOL streams_mult.out

/*

手順2: mult1.netでのサプリメンタル・ロギングの指定

strmadminユーザーとしてmult1.netに接続します。

*/

CONNECT strmadmin@mult1.net

/*

「mult1.netでの最新時刻に基づいた競合解消の構成」の指定に従って、各表の主キーおよび各表の列リストを含む無条件のサプリメンタル・ログ・グループを指定します。各表の列リストには、各表の主キー以外のすべての列が含まれているため、この手順では、表のすべての列を含む各表のサプリメンタル・ログ・グループを作成します。


注意:

  • 便宜上、この例では、単一の無条件ログ・グループに各表の主キー列および更新の競合解消に使用される列を含めます。各表の主キー列を無条件ログ・グループに含め、更新の競合解消に使用される列を条件付きログ・グループに含めることができます。

  • この例では、mult2.netおよびmult3.netで、サプリメンタル・ロギングを明示的に指定する必要はありません。この例の後半で、データ・ポンプを使用して、これらのデータベースでhrmultスキーマ内の表をインスタンス化する際、mult1.netでのサプリメンタル・ロギングの指定がmult2.netおよびmult3.netに保持されます。


*/

ALTER TABLE hrmult.countries ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

ALTER TABLE hrmult.departments ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

ALTER TABLE hrmult.employees ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

ALTER TABLE hrmult.jobs ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

ALTER TABLE hrmult.job_history ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

ALTER TABLE hrmult.locations ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

ALTER TABLE hrmult.regions ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

/*

手順3: mult1.netでの取得プロセスの作成

mult1.nethrmultスキーマ全体に対する変更を取得するように取得プロセスを作成します。また、この手順では、mult1.nethrmultスキーマをインスタンス化のために準備します。この手順の実行後、ユーザーはmult1.nethrmultスキーマ内の表を変更できます。

*/

BEGIN
  DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
    schema_name    => 'hrmult',
    streams_type   => 'capture',
    streams_name   => 'capture_hrmult',
    queue_name     => 'strmadmin.captured_mult1',
    include_dml    => TRUE,
    include_ddl    => TRUE,
    inclusion_rule => TRUE);
END;
/

/*

手順4: mult1.netでの各ソース・データベース用の1つの適用プロセスの作成

mult2.nethrmultスキーマに変更を適用するようにmult1.netを構成します。

*/

BEGIN
  DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
    schema_name     => 'hrmult',
    streams_type    => 'apply',
    streams_name    => 'apply_from_mult2',
    queue_name      => 'strmadmin.from_mult2',
    include_dml     => TRUE,
    include_ddl     => TRUE,
    source_database => 'mult2.net',
    inclusion_rule  => TRUE);
END;
/

/*

mult3.nethrmultスキーマに変更を適用するようにmult1.netを構成します。

*/

BEGIN
  DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
    schema_name     => 'hrmult',
    streams_type    => 'apply',
    streams_name    => 'apply_from_mult3',
    queue_name      => 'strmadmin.from_mult3',
    include_dml     => TRUE,
    include_ddl     => TRUE,
    source_database => 'mult3.net',
    inclusion_rule  => TRUE);
END;
/

/*

手順5: mult1.netでの最新時刻に基づいた競合解消の構成

hrmultスキーマ内の各表に更新競合ハンドラを指定します。各表で、MAXIMUM競合ハンドラの解消列としてtime列を指定します。更新の競合が発生すると、このような競合ハンドラは最新(または最大)時刻のトランザクションを適用し、それより前の(または小さい)時刻のトランザクションを廃棄します。この例では、主キー値が更新されないと想定しているため、列リストには主キーを除く各表のすべての列が含まれます。

*/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'country_name';
  cols(2) := 'region_id';
  cols(3) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.countries',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'department_name';
  cols(2) := 'manager_id';
  cols(3) := 'location_id';
  cols(4) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.departments',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

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           =>  'hrmult.employees',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'job_title';
  cols(2) := 'min_salary';
  cols(3) := 'max_salary';
  cols(4) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.jobs',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'employee_id';
  cols(2) := 'start_date';
  cols(3) := 'end_date';
  cols(4) := 'job_id';
  cols(5) := 'department_id';
  cols(6) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.job_history',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'street_address';
  cols(2) := 'postal_code';
  cols(3) := 'city';
  cols(4) := 'state_province';
  cols(5) := 'country_id';
  cols(6) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.locations',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'region_name';
  cols(2) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.regions',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

/*

手順6: mult1.netでの伝播の構成

mult1.netのキューからmult2.netのキューへのhrmultスキーマ内のDML変更およびDDL変更の伝播を構成およびスケジュールします。

*/

BEGIN
  DBMS_STREAMS_ADM.ADD_SCHEMA_PROPAGATION_RULES(
    schema_name               => 'hrmult',
    streams_name              => 'mult1_to_mult2',
    source_queue_name         => 'strmadmin.captured_mult1',
    destination_queue_name    => 'strmadmin.from_mult1@mult2.net',
    include_dml               => TRUE,
    include_ddl               => TRUE,
    source_database           => 'mult1.net',
    inclusion_rule            => TRUE,
    queue_to_queue            => TRUE);
END;
/

/*

mult1.netのキューからmult3.netのキューへのhrmultスキーマ内のDML変更およびDDL変更の伝播を構成およびスケジュールします。

*/

BEGIN
  DBMS_STREAMS_ADM.ADD_SCHEMA_PROPAGATION_RULES(
    schema_name               => 'hrmult',
    streams_name              => 'mult1_to_mult3',
    source_queue_name         => 'strmadmin.captured_mult1',
    destination_queue_name    => 'strmadmin.from_mult1@mult3.net',
    include_dml               => TRUE,
    include_ddl               => TRUE,
    source_database           => 'mult1.net',
    inclusion_rule            => TRUE,
    queue_to_queue            => TRUE);
END;
/

/*

手順7: mult2.netでの取得プロセスの作成

strmadminユーザーとしてmult2.netに接続します。

*/

CONNECT strmadmin@mult2.net

/*

mult2.nethrmultスキーマ全体に対する変更を取得するように取得プロセスを作成します。また、この手順では、mult2.nethrmultスキーマをインスタンス化のために準備します。

*/

BEGIN
  DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
    schema_name    => 'hrmult',
    streams_type   => 'capture',
    streams_name   => 'capture_hrmult',
    queue_name     => 'strmadmin.captured_mult2',
    include_dml    => TRUE,
    include_ddl    => TRUE,
    inclusion_rule => TRUE);
END;
/

/*

手順8: 他のデータベースでのmult2.netに対するインスタンス化SCNの設定

この例では、すべてのデータベースにhrmultスキーマがすでに存在します。手順16mult2.netおよびmult3.netでインスタンス化されるまで、スキーマ内の表はmult1.netにのみ存在します。インスタンス化は、mult1.netからの表のインポートを使用して実行されます。これらのインポート操作によって、mult2.netおよびmult3.netmult1.netでのスキーマのインスタンス化SCNが自動的に設定されます。

ただし、mult2.netおよびmult3.netのインスタンス化SCNは、環境内の他のサイトでは自動的に設定されません。この手順では、mult1.netおよびmult3.netmult2.netのスキーマのインスタンス化SCNを手動で設定します。mult2.netでの現行のSCNは、mult2.netDBMS_FLASHBACKパッケージのGET_SYSTEM_CHANGE_NUMBERファンクションを使用して取得できます。このSCNは、mult1.netおよびmult3.netDBMS_APPLY_ADMパッケージのSET_SCHEMA_INSTANTIATION_SCNプロシージャを実行するために使用されます。

SET_SCHEMA_INSTANTIATION_SCNプロシージャを使用すると、適用プロセスで無視されるスキーマのDDL LCRと、適用プロセスで適用されるスキーマのDDL LCRを制御できます。ソース・データベースからのスキーマ内のデータベース・オブジェクトに関するDDL LCRのコミットSCNが、一部の接続先データベースでそのデータベース・オブジェクトのインスタンス化SCN以下であれば、接続先データベースの適用プロセスではDDL LCRが無視されます。それ以外の場合は、適用プロセスによってDDL LCRが適用されます。

SET_SCHEMA_INSTANTIATION_SCNプロシージャは、mult2.netで表がインスタンス化される前に実行し、ローカルの取得プロセスがすでに構成されているため、インスタンス化後の表ごとにSET_TABLE_INSTANTIATION_SCNプロシージャを実行する必要はありません。この例では、mult1.netmult3.netの両方の適用プロセスは、この手順で取得したSCNの後にコミットされたSCNを持つhrmultスキーマ内の表にトランザクションを適用します。


注意:

  • 存在しないスキーマをインスタンス化する場合、スキーマのインスタンス化SCNのかわりに、グローバルのインスタンス化SCNを設定できます。

  • インスタンス化SCNを設定する前に表がインスタンス化された場合は、スキーマ内の各表に対してスキーマのインスタンス化SCNおよびインスタンス化SCNを設定する必要があります。


*/

DECLARE
  iscn  NUMBER;         -- Variable to hold instantiation SCN value
BEGIN
  iscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();
  DBMS_APPLY_ADM.SET_SCHEMA_INSTANTIATION_SCN@MULT1.NET(
    source_schema_name    => 'hrmult',
    source_database_name  => 'mult2.net',
    instantiation_scn     => iscn);
  DBMS_APPLY_ADM.SET_SCHEMA_INSTANTIATION_SCN@MULT3.NET(
    source_schema_name    => 'hrmult',
    source_database_name  => 'mult2.net',
    instantiation_scn     => iscn);
END;
/

/*

手順9: mult2.netでの各ソース・データベース用の1つの適用プロセスの作成

mult1.nethrmultスキーマに変更を適用するようにmult2.netを構成します。

*/

BEGIN
  DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
    schema_name     => 'hrmult',
    streams_type    => 'apply',
    streams_name    => 'apply_from_mult1',
    queue_name      => 'strmadmin.from_mult1',
    include_dml     => TRUE,
    include_ddl     => TRUE,
    source_database => 'mult1.net',
    inclusion_rule  => TRUE);
END;
/

/*

mult3.nethrmultスキーマに変更を適用するようにmult2.netを構成します。

*/

BEGIN
  DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
    schema_name     => 'hrmult',
    streams_type    => 'apply',
    streams_name    => 'apply_from_mult3',
    queue_name      => 'strmadmin.from_mult3',
    include_dml     => TRUE,
    include_ddl     => TRUE,
    source_database => 'mult3.net',
    inclusion_rule  => TRUE);
END;
/

/*

手順10: mult2.netでの伝播の構成

mult2.netのキューからmult1.netのキューへのhrmultスキーマ内のDML変更およびDDL変更の伝播を構成およびスケジュールします。

*/

BEGIN
  DBMS_STREAMS_ADM.ADD_SCHEMA_PROPAGATION_RULES(
    schema_name             => 'hrmult',
    streams_name            => 'mult2_to_mult1',
    source_queue_name       => 'strmadmin.captured_mult2',
    destination_queue_name  => 'strmadmin.from_mult2@mult1.net',
    include_dml             => TRUE,
    include_ddl             => TRUE,
    source_database         => 'mult2.net',
    inclusion_rule          => TRUE,
    queue_to_queue          => TRUE);
END;
/

/*

mult2.netのキューからmult3.netのキューへのhrmultスキーマ内のDML変更およびDDL変更の伝播を構成およびスケジュールします。

*/

BEGIN
  DBMS_STREAMS_ADM.ADD_SCHEMA_PROPAGATION_RULES(
    schema_name             => 'hrmult',
    streams_name            => 'mult2_to_mult3',
    source_queue_name       => 'strmadmin.captured_mult2',
    destination_queue_name  => 'strmadmin.from_mult2@mult3.net',
    include_dml             => TRUE,
    include_ddl             => TRUE,
    source_database         => 'mult2.net',
    inclusion_rule          => TRUE,
    queue_to_queue          => TRUE);
END;
/

/*

手順11: mult3.netでの取得プロセスの作成

strmadminユーザーとしてmult3.netに接続します。

*/

CONNECT strmadmin@mult3.net

/*

mult3.nethrmultスキーマ全体に対する変更を取得するように取得プロセスを作成します。また、この手順ではmult3.nethrmultスキーマをインスタンス化のために準備します。

*/

BEGIN
  DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
    schema_name    => 'hrmult',
    streams_type   => 'capture',
    streams_name   => 'capture_hrmult',
    queue_name     => 'strmadmin.captured_mult3',
    include_dml    => TRUE,
    include_ddl    => TRUE,
    inclusion_rule => TRUE);
END;
/

/*

手順12: 他のデータベースでのmult3.netに対するインスタンス化SCNの設定

この例では、すべてのデータベースにhrmultスキーマがすでに存在します。手順16mult2.netおよびmult3.netでインスタンス化されるまで、スキーマ内の表はmult1.netにのみ存在します。インスタンス化は、mult1.netからの表のインポートを使用して実行されます。これらのインポート操作によって、mult2.netおよびmult3.netmult1.netでのスキーマのインスタンス化SCNが自動的に設定されます。

ただし、mult2.netおよびmult3.netのインスタンス化SCNは、環境内の他のサイトでは自動的に設定されません。この手順では、mult1.netおよびmult2.netmult3.netのスキーマのインスタンス化SCNを手動で設定します。mult3.netでの現行のSCNは、mult3.netDBMS_FLASHBACKパッケージのGET_SYSTEM_CHANGE_NUMBERファンクションを使用して取得できます。このSCNは、mult1.netおよびmult2.netDBMS_APPLY_ADMパッケージのSET_SCHEMA_INSTANTIATION_SCNプロシージャを実行するために使用されます。

SET_SCHEMA_INSTANTIATION_SCNプロシージャを使用すると、適用プロセスで無視されるスキーマのDDL LCRと、適用プロセスで適用されるスキーマのDDL LCRを制御できます。ソース・データベースからのスキーマ内のデータベース・オブジェクトに関するDDL LCRのコミットSCNが、一部の接続先データベースでそのデータベース・オブジェクトのインスタンス化SCN以下であれば、接続先データベースの適用プロセスではDDL LCRが無視されます。それ以外の場合は、適用プロセスによってDDL LCRが適用されます。

SET_SCHEMA_INSTANTIATION_SCNプロシージャは、mult3.netで表がインスタンス化される前に実行し、ローカルの取得プロセスがすでに構成されているため、インスタンス化後の表ごとにSET_TABLE_INSTANTIATION_SCNプロシージャを実行する必要はありません。この例では、mult1.netmult2.netの両方の適用プロセスは、この手順で取得したSCNの後にコミットされたSCNを持つhrmultスキーマ内の表にトランザクションを適用します。


注意:

  • 存在しないスキーマをインスタンス化する場合、スキーマのインスタンス化SCNのかわりに、グローバルのインスタンス化SCNを設定できます。

  • インスタンス化SCNを設定する前に表がインスタンス化された場合は、スキーマ内の各表に対してスキーマのインスタンス化SCNおよびインスタンス化SCNを設定する必要があります。


*/

DECLARE
  iscn  NUMBER;         -- Variable to hold instantiation SCN value
BEGIN
  iscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();
  DBMS_APPLY_ADM.SET_SCHEMA_INSTANTIATION_SCN@MULT1.NET(
    source_schema_name    => 'hrmult',
    source_database_name  => 'mult3.net',
    instantiation_scn     => iscn);
  DBMS_APPLY_ADM.SET_SCHEMA_INSTANTIATION_SCN@MULT2.NET(
    source_schema_name    => 'hrmult',
    source_database_name  => 'mult3.net',
    instantiation_scn     => iscn);
END;
/

/*

手順13: mult3.netでの各ソース・データベース用の1つの適用プロセスの作成

mult1.nethrmultスキーマに変更を適用するようにmult3.netを構成します。

*/

BEGIN
  DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
    schema_name     => 'hrmult',
    streams_type    => 'apply',
    streams_name    => 'apply_from_mult1',
    queue_name      => 'strmadmin.from_mult1',
    include_dml     => TRUE,
    include_ddl     => TRUE,
    source_database => 'mult1.net',
    inclusion_rule  => TRUE);
END;
/

/*

mult2.nethrmultスキーマに変更を適用するようにmult3.netを構成します。

*/

BEGIN
  DBMS_STREAMS_ADM.ADD_SCHEMA_RULES(
    schema_name     => 'hrmult',
    streams_type    => 'apply',
    streams_name    => 'apply_from_mult2',
    queue_name      => 'strmadmin.from_mult2',
    include_dml     => TRUE,
    include_ddl     => TRUE,
    source_database => 'mult2.net',
    inclusion_rule  => TRUE);
END;
/

/*

手順14: mult3.netでの伝播の構成

mult3.netのキューからmult1.netのキューへのhrmultスキーマ内のDML変更およびDDL変更の伝播を構成およびスケジュールします。

*/

BEGIN
  DBMS_STREAMS_ADM.ADD_SCHEMA_PROPAGATION_RULES(
    schema_name             => 'hrmult',
    streams_name            => 'mult3_to_mult1',
    source_queue_name       => 'strmadmin.captured_mult3',
    destination_queue_name  => 'strmadmin.from_mult3@mult1.net',
    include_dml             => TRUE,
    include_ddl             => TRUE,
    source_database         => 'mult3.net',
    inclusion_rule          => TRUE,
    queue_to_queue          => TRUE);
END;
/

/*

mult3.netのキューからmult2.netのキューへのhrmultスキーマ内のDML変更およびDDL変更の伝播を構成およびスケジュールします。

*/

BEGIN
  DBMS_STREAMS_ADM.ADD_SCHEMA_PROPAGATION_RULES(
    schema_name             => 'hrmult',
    streams_name            => 'mult3_to_mult2',
    source_queue_name       => 'strmadmin.captured_mult3',
    destination_queue_name  => 'strmadmin.from_mult3@mult2.net',
    include_dml             => TRUE,
    include_ddl             => TRUE,
    source_database         => 'mult3.net',
    inclusion_rule          => TRUE,
    queue_to_queue          => TRUE);
END;
/

/*

手順15: mult2.netでのhrmultスキーマのインスタンス化

この例では、データ・ポンプを使用してmult1.netからmult2.netへのhrmultスキーマのネットワーク・インポートを実行します。ネットワーク・インポートとは、エクスポート・ダンプ・ファイルを使用せずに、データ・ポンプでmult1.netからスキーマのデータベース・オブジェクトをインポートすることを意味します。


参照:

インポートを実行する方法の詳細は、『Oracle Databaseユーティリティ』を参照してください。

strmadminユーザーとしてmult2.netに接続します。

*/

CONNECT strmadmin@mult2.net

/*

この例では、DBMS_DATAPUMPパッケージを使用してスキーマ・レベルのインポートを実行します。簡略化するために、どのAPIコールからの例外も捕捉されません。ただし、例外ハンドラを定義し、障害発生時にGET_STATUSをコールしてエラーの詳細情報を取得することをお薦めします。インポートを監視する場合は、インポート・データベースでDBA_DATAPUMP_JOBSデータ・ディクショナリ・ビューを問い合せます。

*/

SET SERVEROUTPUT ON
DECLARE
  h1                 NUMBER;         -- Data Pump job handle
  mult2_instantscn   NUMBER;         -- Variable to hold current source SCN
  job_state          VARCHAR2(30);   -- To keep track of job state
  js                 ku$_JobStatus;  -- The job status from GET_STATUS
  sts                ku$_Status;     -- The status object returned by GET_STATUS
  job_not_exist    exception;
  pragma exception_init(job_not_exist, -31626);
BEGIN
-- Create a (user-named) Data Pump job to do a schema-level import.
  h1 := DBMS_DATAPUMP.OPEN(
          operation   => 'IMPORT',
          job_mode    => 'SCHEMA',
          remote_link => 'MULT1.NET',
          job_name    => 'dp_mult2');
-- A metadata filter is used to specify the schema that owns the tables
-- that will be imported.
  DBMS_DATAPUMP.METADATA_FILTER(
    handle    => h1,
    name      => 'SCHEMA_EXPR',
    value     => '=''HRMULT''');
-- Get the current SCN of the source database, and set the FLASHBACK_SCN
-- parameter to this value to ensure consistency between all of the
-- objects in the schema.
  mult2_instantscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER@mult1.net();
  DBMS_DATAPUMP.SET_PARAMETER(
    handle => h1,
    name   => 'FLASHBACK_SCN',
    value  => mult2_instantscn);
-- Start the job.
  DBMS_DATAPUMP.START_JOB(h1);
-- The import job should be running. In the following loop, the job
-- is monitored until it completes.
  job_state := 'UNDEFINED';
  BEGIN
    WHILE (job_state != 'COMPLETED') AND (job_state != 'STOPPED') LOOP
      sts:=DBMS_DATAPUMP.GET_STATUS(
             handle  => h1,
             mask    => DBMS_DATAPUMP.KU$_STATUS_JOB_ERROR +
                        DBMS_DATAPUMP.KU$_STATUS_JOB_STATUS +
                        DBMS_DATAPUMP.KU$_STATUS_WIP,
             timeout => -1);
      js := sts.job_status;
      DBMS_LOCK.SLEEP(10);
      job_state := js.state;
    END LOOP;
  -- Gets an exception when job no longer exists
    EXCEPTION WHEN job_not_exist THEN
      DBMS_OUTPUT.PUT_LINE('Data Pump job has completed');
      DBMS_OUTPUT.PUT_LINE('Instantiation SCN: ' ||mult2_instantscn);
  END;
END;
/

/*

手順16: mult3.netでのhrmultスキーマのインスタンス化

この例では、データ・ポンプを使用してmult1.netからmult3.netへのhrmultスキーマのネットワーク・インポートを実行します。ネットワーク・インポートとは、エクスポート・ダンプ・ファイルを使用せずに、データ・ポンプでmult1.netからスキーマのデータベース・オブジェクトをインポートすることを意味します。


参照:

インポートを実行する方法の詳細は、『Oracle Databaseユーティリティ』を参照してください。

strmadminユーザーとしてmult3.netに接続します。

*/

CONNECT strmadmin@mult3.net

/*

この例では、DBMS_DATAPUMPパッケージを使用して表のインポートを実行します。簡略化するために、どのAPIコールからの例外も捕捉されません。ただし、例外ハンドラを定義し、障害発生時にGET_STATUSをコールしてエラーの詳細情報を取得することをお薦めします。インポートを監視する場合は、インポート・データベースでDBA_DATAPUMP_JOBSデータ・ディクショナリ・ビューを問い合せます。

*/

SET SERVEROUTPUT ON
DECLARE
  h1                 NUMBER;         -- Data Pump job handle
  mult3_instantscn   NUMBER;         -- Variable to hold current source SCN
  job_state          VARCHAR2(30);   -- To keep track of job state
  js                 ku$_JobStatus;  -- The job status from GET_STATUS
  sts                ku$_Status;     -- The status object returned by GET_STATUS
  job_not_exist    exception;
  pragma exception_init(job_not_exist, -31626);
BEGIN
-- Create a (user-named) Data Pump job to do a schema-level import.
  h1 := DBMS_DATAPUMP.OPEN(
          operation   => 'IMPORT',
          job_mode    => 'SCHEMA',
          remote_link => 'MULT1.NET',
          job_name    => 'dp_mult3');
-- A metadata filter is used to specify the schema that owns the tables
-- that will be imported.
  DBMS_DATAPUMP.METADATA_FILTER(
    handle    => h1,
    name      => 'SCHEMA_EXPR',
    value     => '=''HRMULT''');
-- Get the current SCN of the source database, and set the FLASHBACK_SCN
-- parameter to this value to ensure consistency between all of the
-- objects in the schema.
  mult3_instantscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER@mult1.net();
  DBMS_DATAPUMP.SET_PARAMETER(
    handle => h1,
    name   => 'FLASHBACK_SCN',
    value  => mult3_instantscn);
-- Start the job.
  DBMS_DATAPUMP.START_JOB(h1);
-- The import job should be running. In the following loop, the job
-- is monitored until it completes.
  job_state := 'UNDEFINED';
  BEGIN
    WHILE (job_state != 'COMPLETED') AND (job_state != 'STOPPED') LOOP
      sts:=DBMS_DATAPUMP.GET_STATUS(
             handle  => h1,
             mask    => DBMS_DATAPUMP.KU$_STATUS_JOB_ERROR +
                        DBMS_DATAPUMP.KU$_STATUS_JOB_STATUS +
                        DBMS_DATAPUMP.KU$_STATUS_WIP,
             timeout => -1);
      js := sts.job_status;
      DBMS_LOCK.SLEEP(10);
      job_state := js.state;
    END LOOP;
  -- Gets an exception when job no longer exists
    EXCEPTION WHEN job_not_exist THEN
      DBMS_OUTPUT.PUT_LINE('Data Pump job has completed');
      DBMS_OUTPUT.PUT_LINE('Instantiation SCN: ' ||mult3_instantscn);
  END;
END;
/

/*

手順17: mult2.netでの最新時刻に基づいた競合解消の構成

strmadminユーザーとしてmult2.netに接続します。

*/

CONNECT strmadmin@mult2.net

/*

hrmultスキーマ内の各表に更新競合ハンドラを指定します。各表で、MAXIMUM競合ハンドラの解消列としてtime列を指定します。更新の競合が発生すると、このような競合ハンドラは最新(または最大)時刻のトランザクションを適用し、それより前の(または小さい)時刻のトランザクションを廃棄します。

*/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'country_name';
  cols(2) := 'region_id';
  cols(3) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.countries',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'department_name';
  cols(2) := 'manager_id';
  cols(3) := 'location_id';
  cols(4) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.departments',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

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           =>  'hrmult.employees',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'job_title';
  cols(2) := 'min_salary';
  cols(3) := 'max_salary';
  cols(4) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.jobs',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'employee_id';
  cols(2) := 'start_date';
  cols(3) := 'end_date';
  cols(4) := 'job_id';
  cols(5) := 'department_id';
  cols(6) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.job_history',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'street_address';
  cols(2) := 'postal_code';
  cols(3) := 'city';
  cols(4) := 'state_province';
  cols(5) := 'country_id';
  cols(6) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.locations',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'region_name';
  cols(2) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.regions',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

/*

手順18: mult2.netでの適用プロセスの起動

mult2.netで両方の適用プロセスを起動します。

*/

BEGIN
  DBMS_APPLY_ADM.START_APPLY(
    apply_name  => 'apply_from_mult1');
END;
/

BEGIN
  DBMS_APPLY_ADM.START_APPLY(
    apply_name  => 'apply_from_mult3');
END;
/

/*

手順19: mult3.netでの最新時刻に基づいた競合解消の構成

strmadminユーザーとしてmult3.netに接続します。

*/

CONNECT strmadmin@mult3.net

/*

hrmultスキーマ内の各表に更新競合ハンドラを指定します。各表で、MAXIMUM競合ハンドラの解消列としてtime列を指定します。更新の競合が発生すると、このような競合ハンドラは最新(または最大)時刻のトランザクションを適用し、それより前の(または小さい)時刻のトランザクションを廃棄します。

*/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'country_name';
  cols(2) := 'region_id';
  cols(3) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.countries',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'department_name';
  cols(2) := 'manager_id';
  cols(3) := 'location_id';
  cols(4) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.departments',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

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           =>  'hrmult.employees',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'job_title';
  cols(2) := 'min_salary';
  cols(3) := 'max_salary';
  cols(4) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.jobs',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'employee_id';
  cols(2) := 'start_date';
  cols(3) := 'end_date';
  cols(4) := 'job_id';
  cols(5) := 'department_id';
  cols(6) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.job_history',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'street_address';
  cols(2) := 'postal_code';
  cols(3) := 'city';
  cols(4) := 'state_province';
  cols(5) := 'country_id';
  cols(6) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.locations',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

DECLARE
  cols  DBMS_UTILITY.NAME_ARRAY;
BEGIN
  cols(1) := 'region_name';
  cols(2) := 'time';
  DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(
    object_name           =>  'hrmult.regions',
    method_name           =>  'MAXIMUM',
    resolution_column     =>  'time',
    column_list           =>  cols);
END;
/

/*

手順20: mult3.netでの適用プロセスの起動

mult3.netで両方の適用プロセスを起動します。

*/

BEGIN
  DBMS_APPLY_ADM.START_APPLY(
    apply_name  => 'apply_from_mult1');
END;
/

BEGIN
  DBMS_APPLY_ADM.START_APPLY(
    apply_name  => 'apply_from_mult2');
END;
/

/*

手順21: mult1.netでの適用プロセスの起動

strmadminユーザーとしてmult1.netに接続します。

*/

CONNECT strmadmin@mult1.net

/*

mult1.netで両方の適用プロセスを起動します。

*/

BEGIN
  DBMS_APPLY_ADM.START_APPLY(
    apply_name  => 'apply_from_mult2');
END;
/

BEGIN
  DBMS_APPLY_ADM.START_APPLY(
    apply_name  => 'apply_from_mult3');
END;
/

/*

手順22: mult1.netでの取得プロセスの起動

mult1.netで取得プロセスを起動します。

*/

BEGIN
  DBMS_CAPTURE_ADM.START_CAPTURE(
    capture_name  => 'capture_hrmult');
END;
/

/*

手順23: mult2.netでの取得プロセスの起動

strmadminユーザーとしてmult2.netに接続します。

*/

CONNECT strmadmin@mult2.net

/*

mult2.netで取得プロセスを起動します。

*/

BEGIN
  DBMS_CAPTURE_ADM.START_CAPTURE(
    capture_name  => 'capture_hrmult');
END;
/

/*

手順24: mult3.netでの取得プロセスの起動

strmadminユーザーとしてmult3.netに接続します。

*/

CONNECT strmadmin@mult3.net

/*

mult3.netで取得プロセスを起動します。

*/

BEGIN
  DBMS_CAPTURE_ADM.START_CAPTURE(
    capture_name  => 'capture_hrmult');
END;
/

SET ECHO OFF

/*

手順25: スプール結果のチェック

streams_mult.outスプール・ファイルをチェックして、このスクリプトの完了後にすべてのアクションが正常に終了していることを確認します。

*/

SET ECHO OFF
SPOOL OFF

/*************************** END OF SCRIPT ******************************/

参照:

データベース・オブジェクトまたはデータベースをレプリケーション環境に追加する方法の概要は、第8章「Oracle Streamsレプリケーション環境への追加」を参照してください。

hrmultスキーマ内の表に対するDML変更およびDDL変更

環境内の任意のデータベースのhrmultスキーマ内の表に対して、DML変更およびDDL変更を行うことができます。これらの変更は、環境内の他のデータベースにレプリケートされ、問合せを実行してそれらのレプリケートされたデータを表示できます。

たとえば、次の手順を実行して、mult1.netおよびmult2.nethrmult.employees表に対してDML変更を行います。前述の手順で構成した更新競合ハンドラで更新の競合が解消されることを確認するには、これらの2つのデータベースの同じ行を変更し、ほぼ同時に変更をコミットします。環境内の各データベースで変更された行を問い合せ、変更が適切に取得、伝播および適用されたことを確認できます。

また、mult3.nethrmult.jobs表に対してDDL変更を行い、変更がmult3.netで取得され、環境内の他のデータベースに伝播され、これらのデータベースで適用されることも確認できます。


手順1: mult1.netおよびmult2.netでのhrmult.employeesに対するDML変更

次の変更を行います。 競合をシミュレートするには、これらの変更をほぼ同時にコミットします。ただし、mult1.netでの変更をコミットした後にmult2.netでの変更をコミットします。 各データベースの更新競合ハンドラによって、競合が解消されます。

CONNECT hrmult@mult1.net
Enter password: password

UPDATE hrmult.employees SET salary=9000 WHERE employee_id=206;
COMMIT;

CONNECT hrmult@mult2.net
Enter password: password

UPDATE hrmult.employees SET salary=10000 WHERE employee_id=206;
COMMIT;

手順2: mult3.netでのhrmult.jobs表の変更

job_title列の名前をjob_nameに変更して、hrmult.jobs表を変更します。

CONNECT hrmult@mult3.net
Enter password: password

ALTER TABLE hrmult.jobs RENAME COLUMN job_title TO job_name;

手順3: 各データベースでのhrmult.employees表の問合せ

手順1で実行した変更が取得、伝播および適用されるまで待ってから、次の問合せを実行して、UPDATE変更が各データベースで適用されていることを確認します。

CONNECT hrmult@mult1.net
Enter password: password

SELECT salary FROM hrmult.employees WHERE employee_id=206;

CONNECT hrmult@mult2.net
Enter password: password

SELECT salary FROM hrmult.employees WHERE employee_id=206;

CONNECT hrmult@mult3.net
Enter password: password

SELECT salary FROM hrmult.employees WHERE employee_id=206;

すべての問合せで、salaryの値が10000と表示されるはずです。 各データベースの更新競合ハンドラによって、行に対する最新の変更を適用して競合が解消されています。 ここでは、行に対する最新の変更は、手順1mult2.netデータベースで行われました。

手順4: 各データベースでのhrmult.jobs表の定義の表示

手順2で実行した変更が取得、伝播および適用されるまで待ってから、各データベースでhrmult.jobs表の定義を表示し、ALTER TABLE変更が正常に伝播および適用されていることを確認します。

CONNECT hrmult@mult1.net
Enter password: password

DESC hrmult.jobs

CONNECT hrmult@mult2.net
Enter password: password

DESC hrmult.jobs

CONNECT hrmult@mult3.net
Enter password: password

DESC hrmult.jobs

各データベースでは、表の2列目にjob_nameが表示されているはずです。