ヘッダーをスキップ
Oracle® Database 2日でデータ・レプリケーションおよび統合ガイド
11g リリース2(11.2)
B56305-03
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

10 データの比較および収束

この章では、2つの異なるデータベースにある共有データベース・オブジェクト内のデータを比較する方法を説明します。共有データベース・オブジェクト内の相違データを収束する方法も説明します。

この章は次の項で構成されています。


関連項目:


異なるデータベース内のデータの比較および収束の概要

2つ以上のデータベースでデータベース・オブジェクトを共有できます。同じデータベース・オブジェクトのコピーが複数のデータベースに存在している場合、データベース・オブジェクトは共有データベース・オブジェクトです。共有データベース・オブジェクトは、データ・レプリケーションによってメンテナンスできます。たとえば、マテリアライズド・ビューまたはOracle Streamsコンポーネントは、データベース・オブジェクトをレプリケートし、複数のデータベースでそれらをメンテナンスできます。カスタム・アプリケーションも、共有データベース・オブジェクトをメンテナンスできます。通常、レプリケーション環境では、データを含むオブジェクト(表など)と、その他のタイプのデータベース・オブジェクト(索引など)を共有します。

1つのデータベースで共有データベース・オブジェクトに変更が加えられた場合、変更が転送され、データベース・オブジェクトを共有する他の各データベースに加えられます。こうして、レプリケーション環境は各データベースの共有データベース・オブジェクトを同期します。

データを含む共有データベース・オブジェクトは、異なるデータベースで一貫性がなくなることがあります。つまり、データは共有データベース・オブジェクトの異なる・インスタンスで拡散します。たとえば、データベース・オブジェクトが表の場合は、表の1つのインスタンスが表の別のインスタンスよりも多くの行を持つこと、または表の2つのインスタンスが同じ行に異なるデータを持つことがあります。

Oracle Streamsレプリケーション環境で共有データベース・オブジェクトが拡散する場合、通常は次のいずれかの理由です。

データ拡散の一般的な原因は、ネットワークの問題、不正な構成またはユーザー・エラーです。共有データベース・オブジェクトが、マテリアライズド・ビューを使用するレプリケーション環境で拡散する場合は、マテリアライズド・ビューのリフレッシュに問題がある可能性があります。

DBMS_COMPARISONパッケージを使用して、異なるデータベースのデータベース・オブジェクトを比較し、差異を識別できます。このパッケージでは、異なるデータベースで一貫するようにデータベース・オブジェクトを収束させることもできます。DBMS_COMPARISONパッケージは、Oracle Databaseとともに必ずインストールされるOracle提供のPL/SQLパッケージです。

DBMS_COMPARISONパッケージは、次のタイプのデータベース・オブジェクトの比較および収束を行うことができます。

異なるデータベースにある異なるタイプのデータベース・オブジェクトの比較および収束を行うことができます。たとえば、あるデータベースにある表と、別のデータベースにあるマテリアライズド・ビューの比較および収束を行うことができます。

このマニュアルの例では、共有データベース・オブジェクトが2つのデータベースで同じ名前を持ち、データベース・オブジェクト全体が比較および収束されています。ただし、DBMS_COMPARISONパッケージは、異なるデータベースにある共有データベース・オブジェクトの差異について柔軟性を提供します。比較されるデータベース・オブジェクトは、必ずしも同じ名前を持つ必要はありません。また、対応する列が同じデータ型である場合、データベース・オブジェクト内で列名が異なっていてもかまいません。共有データベース・オブジェクト全体、または列および行のサブセットの比較および収束を行うことができます。

比較を作成するには、DBMS_COMPARISONパッケージのCREATE_COMPARISONプロシージャを使用します。このプロシージャは、共有データベース・オブジェクトの1つ以上の索引列を識別します。DBMS_COMPARISONパッケージは、索引列として使用できる少なくとも1つの列を識別できる必要があります。指定されたデータベース・オブジェクトに、索引列として使用できる列がない場合、CREATE_COMPARISONプロシージャはデータベース・オブジェクトの比較を作成できません。


注意:

環境に、拡散した共有データベース・オブジェクトがある場合は、問題の原因を調査して解決する必要があります。DBMS_COMPARISONパッケージは共有データベース・オブジェクトの比較および収束を行うことができますが、これらのデータベース・オブジェクトは拡散しないことをお薦めします。


関連項目:

  • DBMS_COMPARISONパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。

  • DBMS_COMPARISONパッケージの高度な機能の使用方法の詳細は、『Oracle Streamsレプリケーション管理者ガイド』を参照してください。


チュートリアル: データの比較および収束の準備

2つのデータベースでhr.departments表を共有するとします。この表を異なるデータベースで比較して、データが一貫しているかどうかを確認します。2つのデータベースで表が拡散している場合は、これらを収束させて一貫させます。

このチュートリアルを実行する前に、次の前提条件を満たします。

この例では、データベースのグローバル名はii1.example.comおよびii2.example.comですが、使用している環境で、前提条件を満たす任意の2つのデータベースをかわりに使用できます。

ii1.example.comおよびii2.example.comデータベースのhr.departments表の比較および収束を準備するには: 

  1. この例の目的を満たすために、2つのデータベースでhr.departments表を拡散させます。

    1. コマンドラインでSQL*Plusを開き、ii2.example.comデータベースにhrユーザーとして接続してください。

      SQL*Plusの起動の詳細は、『Oracle Database 2日でデータベース管理者』を参照してください。

    2. hr.departments表で、department_idが 270と等しい部門を削除します。

      DELETE FROM hr.departments WHERE department_id=270;
      COMMIT;
      
    3. hr.departments表で、ある行のデータを変更します。

      UPDATE hr.departments SET manager_id=114 WHERE department_id=10;
      COMMIT;
      
    4. hr.departments表に行を挿入します。

      INSERT INTO hr.departments VALUES(280, 'Bean Counters', 108, 2700);
      COMMIT;
      
    5. SQL*Plusを終了します。

      EXIT;
      

    注意:

    通常、手順1は不要です。この例では、2つのデータベースでhr.departments表を分散するために含まれています。

  2. ii1.example.comデータベースからii2.example.comデータベースへのデータベース・リンクを作成します。

    データベース・リンクは、ii1.example.comの管理ユーザーのスキーマからii2.example.comの管理ユーザーのスキーマに接続する必要があります。両方のデータベースの管理ユーザーは、hr.departments表にアクセスして変更するために必要な権限と、DBMS_COMPARISONパッケージのサブプログラムを実行するために必要な権限を持っている必要があります。どのユーザーがこれらの権限を持っているかが不明な場合は、SYSTEMユーザーを使用します。また、データベース・リンクの名前とサービス名は、どちらもii2.example.comである必要があります。詳細は、「チュートリアル: データベース・リンクの作成」を参照してください。

チュートリアル: 2つの異なるデータベース内のデータの比較

この例は、「チュートリアル: データの比較および収束の準備」で説明したシナリオの続きです。先に進む前に、その項の手順を完了してください。

DBMS_COMPARISONパッケージのCREATE_COMPARISONプロシージャを使用して、2つの異なるデータベースにある共有データベース・オブジェクトの比較を定義できます。比較が定義された後で、このパッケージのCOMPAREファンクションを使用して、比較で指定したデータベース・オブジェクトを現在の時点で比較できます。 COMPAREファンクションは、特定の比較に対して複数回実行できます。ファンクションを実行するたびに、データベース・オブジェクトのスキャンが1回以上行われ、各スキャンが独自のスキャンIDを持ちます。

ii1.example.comおよびii2.example.comデータベースのhr.departments表全体を比較するには: 

  1. コマンドラインでSQL*Plusを開き、「チュートリアル: データの比較および収束の準備」で作成したデータベース・リンクを所有する管理ユーザーとしてii1.example.comデータベースに接続します。たとえば、SYSTEMユーザーがデータベース・リンクを所有する場合は、SYSTEMユーザーとして接続します。

    sqlplus system@ii1.example.com
    Enter password: password
    

    SQL*Plusの起動の詳細は、『Oracle Database 2日でデータベース管理者』を参照してください。

  2. CREATE_COMPARISONプロシージャを実行して、hr.departments表の比較を作成します。

    BEGIN
      DBMS_COMPARISON.CREATE_COMPARISON(
        comparison_name => 'compare_departments',
        schema_name     => 'hr',
        object_name     => 'departments',
        dblink_name     => 'ii2.example.com');
    END;
    /
    

    新しい比較の名前はcompare_departmentsであることに注意してください。この比較は、CREATE_COMPARISONプロシージャを実行するユーザーが所有します。

  3. COMPAREファンクションを実行して、2つのデータベースのhr.departments表を比較します。

    SET SERVEROUTPUT ON
    DECLARE
      consistent   BOOLEAN;
      scan_info    DBMS_COMPARISON.COMPARISON_TYPE;
    BEGIN
      consistent := DBMS_COMPARISON.COMPARE(
                      comparison_name => 'compare_departments',
                      scan_info       => scan_info,
                      perform_row_dif => TRUE);
      DBMS_OUTPUT.PUT_LINE('Scan ID: '||scan_info.scan_id);
      IF consistent=TRUE THEN
        DBMS_OUTPUT.PUT_LINE('No differences were found.');
      ELSE
        DBMS_OUTPUT.PUT_LINE('Differences were found.');
      END IF;
    END;
    /
    
    Scan ID: 1
    Differences were found.
     
    PL/SQL procedure successfully completed.
    

    手順2で作成した比較の名前をcomparison_nameパラメータに指定します。

    ファクションは、比較のスキャンIDを出力します。比較に関する情報をデータ・ディクショナリ・ビューに問い合せる場合、およびデータベース・オブジェクトを収束させる場合は、スキャンIDが重要です。

    ファンクションは、2つのデータベースで表に差異が見つかったかどうかも出力します。

    • ファンクションが「違いが見つかりません」と出力する場合、表は2つのデータベースで一貫しています。

    • ファンクションが「違いが見つかりました」と出力する場合は、表が2つのデータベースで拡散しています。

  4. 前の手順でファンクションから返されたスキャンIDを記録しておきます。この例では、スキャンIDが1であると想定します。

  5. 手順3で差異が見つかった場合は、次の問合せを実行して、見つかった差異の数を表示します。

    COLUMN OWNER HEADING 'Comparison Owner' FORMAT A16
    COLUMN COMPARISON_NAME HEADING 'Comparison Name' FORMAT A20
    COLUMN SCHEMA_NAME HEADING 'Schema Name' FORMAT A11
    COLUMN OBJECT_NAME HEADING 'Object Name' FORMAT A11
    COLUMN CURRENT_DIF_COUNT HEADING 'Differences' FORMAT 9999999
     
    SELECT c.OWNER, 
           c.COMPARISON_NAME, 
           c.SCHEMA_NAME, 
           c.OBJECT_NAME, 
           s.CURRENT_DIF_COUNT 
      FROM DBA_COMPARISON c, DBA_COMPARISON_SCAN s
      WHERE c.COMPARISON_NAME = s.COMPARISON_NAME AND
            c.OWNER           = s.OWNER AND
            s.SCAN_ID         = 1;
    

    問合せのWHERE句に、手順4で記録したスキャンIDを指定します。

    出力は、次のようになります。

    Comparison Owner Comparison Name      Schema Name Object Name Differences
    ---------------- -------------------- ----------- ----------- -----------
    SYSTEM           COMPARE_DEPARTMENTS  HR          DEPARTMENTS           3
    
  6. 比較されているデータベース・オブジェクトのどの行が異なるかを確認するには、次の問合せを実行します。

    COLUMN COLUMN_NAME HEADING 'Index Column' FORMAT A15
    COLUMN INDEX_VALUE HEADING 'Index Value' FORMAT A15
    COLUMN LOCAL_ROWID HEADING 'Local Row Exists?' FORMAT A20
    COLUMN REMOTE_ROWID HEADING 'Remote Row Exists?' FORMAT A20
     
    SELECT c.COLUMN_NAME,
           r.INDEX_VALUE, 
           DECODE(r.LOCAL_ROWID,
                    NULL, 'No',
                          'Yes') LOCAL_ROWID,
           DECODE(r.REMOTE_ROWID,
                    NULL, 'No',
                          'Yes') REMOTE_ROWID
      FROM DBA_COMPARISON_COLUMNS c,
           DBA_COMPARISON_ROW_DIF r,
           DBA_COMPARISON_SCAN s
      WHERE c.COMPARISON_NAME = 'COMPARE_DEPARTMENTS' AND
            r.SCAN_ID         = s.SCAN_ID AND
            s.PARENT_SCAN_ID  = 1 AND
            r.STATUS          = 'DIF' AND
            c.INDEX_COLUMN    = 'Y' AND
            c.COMPARISON_NAME = r.COMPARISON_NAME AND
            c.OWNER           = r.OWNER
      ORDER BY r.INDEX_VALUE;
    

    WHERE句には、比較の名前と比較のスキャンIDを指定します。この例では、比較の名前はcompare_departmentsで、スキャンIDは1です。

    出力は、次のようになります。

    Index Column    Index Value     Local Row Exists?    Remote Row Exists?
    --------------- --------------- -------------------- --------------------
    DEPARTMENT_ID   10              Yes                  Yes
    DEPARTMENT_ID   270             Yes                  No
    DEPARTMENT_ID   280             No                   Yes
    

    この出力は、比較される表の索引列と、共有データベース・オブジェクト内で異なっている各行の索引値を示します。この例では、索引列はhr.departments表の主キー列(department_id)です。出力は、各行の差異のタイプも示します。

    • Local Row Exists?Remote Row Exists?の両方が、ある行に対してYesの場合、その行はデータベース・オブジェクトの両方のインスタンスに存在しますが、行のデータは異なります。

    • ある行についてLocal Row Exists?Yesで、Remote Row Exists?Noの場合、その行はローカル・データベース・オブジェクトに存在しますが、リモート・データベース・オブジェクトには存在しません。

    • ある行についてLocal Row Exists?Noで、Remote Row Exists?Yesの場合、その行はリモート・データベース・オブジェクトに存在しますが、ローカル・データベース・オブジェクトには存在しません。

チュートリアル: 相違データの収束

この例は、「チュートリアル: 2つの異なるデータベース内のデータの比較」で説明したシナリオの続きです。先に進む前に、その項の手順を完了してください。

共有データベース・オブジェクトが2つの異なるデータベースで拡散した場合は、DBMS_COMPARISONパッケージのCONVERGEプロシージャを使用して、データベース・オブジェクトの2つのインスタンスを収束させることができます。CONVERGEプロシージャを正常に実行すると、共有データベース・オブジェクトが2つのデータベースで一貫します。CONVERGEプロシージャを実行するには、次の情報を指定する必要があります。

スキャンIDには、収束させる差異に関する情報が含まれます。この例では、比較の名前はcompare_departmentsで、スキャンIDは 1です。

また、CONVERGEプロシージャを実行する際には、共有データベース・オブジェクトが収束するときに「優先」されるデータベースを指定する必要があります。ローカル・データベースが優先されることを指定した場合は、データが異なるときに、ローカル・データベースのデータベース・オブジェクト内のデータでリモート・データベースのデータベース・オブジェクト内のデータが置換されます。リモート・データベースが優先されることを指定した場合は、データが異なるときに、リモート・データベースのデータベース・オブジェクト内のデータでローカル・データベースのデータベース・オブジェクト内のデータが置換されます。この例では、ローカル・データベースii1.example.comが優先されます。

ii1.example.comおよびii2.example.comデータベースのhr.departments表の相違データを収束させるには: 

  1. コマンドラインでSQL*Plusを開き、「チュートリアル: データの比較および収束の準備」で作成したデータベース・リンクを所有する管理ユーザーとしてii1.example.comデータベースに接続します。たとえば、SYSTEMユーザーがデータベース・リンクを所有する場合は、SYSTEMユーザーとして接続します。

    sqlplus system@ii1.example.com
    Enter password: password
    

    SQL*Plusの起動の詳細は、『Oracle Database 2日でデータベース管理者』を参照してください。

  2. CONVERGEプロシージャを実行して、2つのデータベースのhr.departments表を収束させます。

    SET SERVEROUTPUT ON
    DECLARE
      scan_info    DBMS_COMPARISON.COMPARISON_TYPE;
    BEGIN
      DBMS_COMPARISON.CONVERGE(
        comparison_name  => 'compare_departments',
        scan_id          => 1,
        scan_info        => scan_info,
        converge_options => DBMS_COMPARISON.CMP_CONVERGE_LOCAL_WINS);
      DBMS_OUTPUT.PUT_LINE('Local Rows Merged: '||scan_info.loc_rows_merged);
      DBMS_OUTPUT.PUT_LINE('Remote Rows Merged: '||scan_info.rmt_rows_merged);
      DBMS_OUTPUT.PUT_LINE('Local Rows Deleted: '||scan_info.loc_rows_deleted);
      DBMS_OUTPUT.PUT_LINE('Remote Rows Deleted: '||scan_info.rmt_rows_deleted);
    END;
    /
    
    Local Rows Merged: 0
    Remote Rows Merged: 2
    Local Rows Deleted: 0
    Remote Rows Deleted: 1
    
    PL/SQL procedure successfully completed.
    

CONVERGEプロシージャは、指定されたスキャンで比較されるデータベース・オブジェクトの部分を同期し、行われた変更に関する情報を返します。一部のスキャンは、データベース・オブジェクトのサブセットを比較することがあります。この例では、指定されたスキャンは表全体を比較しました。このため、比較スキャンの完了後に新しい差異が追加されていないと想定すると、表全体が同期されています。

この例では、プロシージャでconverge_optionsパラメータがDBMS_COMPARISON.CMP_CONVERGE_LOCAL_WINSに設定されているためローカル表が優先されます。つまり、2つのデータベースで異なる行については、ローカル・データベースの行によって、リモート・データベースの対応する行が置換されます。一部の行がリモート・データベースに存在し、ローカル・データベースには存在しない場合は、リモート・データベースの余分な行が削除されます。リモート・データベースを優先する場合は、プロシージャでconverge_optionsパラメータをDBMS_COMPARISON.CMP_CONVERGE_REMOTE_WINSに設定します。

また、Oracle Streamsレプリケーション環境の一部である共有データベース・オブジェクトに対してCONVERGEプロシージャを実行する場合は、プロシージャによって行われた変更を他のデータベースにレプリケートしたくないことがあります。この場合は、CONVERGEプロシージャで、次のパラメータを変更がレプリケートされない値に設定できます。

これらのパラメータのいずれかがNULL以外の値に設定されている場合、収束中に変更を行うセッションでタグが設定されます。local_converge_tagパラメータはセッション中にローカル・データベースにタグを設定しますが、remote_converge_tagパラメータはセッション中にリモート・データベースにタグを設定します。CONVERGEプロシージャによって行われた変更をレプリケートしない場合は、これらのパラメータを、Oracle Streams取得プロセスおよび同期取得が変更を取得しないようにする値に設定します。