双方向複製の構成

単方向レプリケーションを設定した後は、逆方向にデータをレプリケートするための追加ステップがいくつかあります。このクイックスタートの例では、2つのクラウド・データベースとしてAutonomous Transaction ProcessingとAutonomous Data Warehouseを使用します。

開始する前に

このクイックスタートを続行するには、同じテナンシおよびリージョンに2つの既存のデータベースが必要です。サンプル・データが必要な場合は、Archive.zipをダウンロードし、ラボ1、タスク3: ATPスキーマのロードの手順に従います

概要

次のステップでは、Oracle Data Pumpを使用してターゲット・データベースをインスタンス化し、同じリージョン内の2つのデータベース間で双方向(2方向)レプリケーションを設定する方法について説明します。

bidirectional.pngの説明が続きます
図bidirectional.pngの説明

タスク1: 環境の設定

  1. デプロイメントを作成します
  2. データベースへの接続を作成します
  3. デプロイメントに接続を割り当てます
  4. サプリメンタル・ロギングを有効にします:
    ALTER DATABASE ADD SUPPLEMENTAL LOG DATA
  5. 次の問合せを実行して、ソース・データベース内のすべての表のsupport_mode=FULLを確認します:
    
    select * from DBA_GOLDENGATE_SUPPORT_MODE where owner = 'SRC_OCIGGLL';
  6. データベースBで次の問合せを実行して、データベース内のすべての表のsupport_mode=FULLを確認します:
    select * from DBA_GOLDENGATE_SUPPORT_MODE where owner = 'SRCMIRROR_OCIGGLL';

タスク2: 両方のデータベースのトランザクション情報およびチェックポイント表の追加

OCI GoldenGateデプロイメント・コンソールで、管理サービスの「構成」画面に移動し、次を実行します:

  1. データベースAおよびBで、トランザクション情報を追加します:
    1. データベースAで、「スキーマ名」にSRC_OCIGGLLと入力します。
    2. データベースBで、「スキーマ名」にSRCMIRROR_OCIGGLLと入力します。

    ノート:

    この例とは異なるデータセットを使用している場合、スキーマ名は一意で、データベース・スキーマの名前と一致している必要があります。
  2. データベースAおよびBで、チェックポイント表を作成します:
    1. データベースAで、「チェックポイント表」に"SRC_OCIGGLL"."ATP_CHECKTABLE"と入力します。
    2. データベースBで、「チェックポイント表」に"SRCMIRROR_OCIGGLL"."CHECKTABLE"と入力します。

タスク3: 統合Extractの作成

統合Extractは、ソース・データベースに対する継続的な変更を取得します。

  1. 「デプロイメント詳細」ページで、「コンソールの起動」をクリックします。
  2. 統合Extractを追加して実行します

    ノート:

    ソース表を指定するために使用できるパラメータの詳細は、「追加の抽出パラメータ・オプション」を参照してください。
    1. 「Extractパラメータ」ページで、EXTTRAIL <extract-name>の下に次の行を追加します:
      -- Capture DDL operations for listed schema tables
      ddl include mapped
      
      -- Add step-by-step history of 
      -- to the report file. Very useful when troubleshooting.
      ddloptions report 
      
      -- Write capture stats per table to the report file daily.
      report at 00:01 
      
      -- Rollover the report file weekly. Useful when IE runs
      -- without being stopped/started for long periods of time to
      -- keep the report files from becoming too large.
      reportrollover at 00:01 on Sunday 
      
      -- Report total operations captured, and operations per second
      -- every 10 minutes.
      reportcount every 10 minutes, rate 
      
      -- Table list for capture
      table SRC_OCIGGLL.*;
      
      -- Exclude changes made by GGADMIN
      tranlogoptions excludeuser ggadmin

    ノート:

    tranlogoptions excludeuser ggadminは、双方向レプリケーション・シナリオでggadminによって適用されるトランザクションの再取得を回避します。
  3. 長時間実行トランザクションを確認します:
    1. ソース・データベースで次のスクリプトを実行します:
      select start_scn, start_time from gv$transaction where start_scn < (select max(start_scn) from dba_capture);

      問合せでなんらかの行が返された場合は、トランザクションのSCNを特定してから、トランザクションをコミットまたはロールバックする必要があります。

タスク4: Oracle Data Pump (ExpDP)を使用したデータのエクスポート

Oracle Data Pump (ExpDP)を使用して、ソース・データベースからOracle Object Storeにデータをエクスポートします。

  1. Oracle Object Storeバケットを作成します

    エクスポートおよびインポート・スクリプトで使用するネームスペースおよびバケット名をメモしておいてください。

  2. 認証トークンを作成し、後で使用するためにトークン文字列をコピーしてテキスト・エディタに貼り付けます。
  3. ソース・データベースに資格証明を作成し、<user-name>および<token>を、前のステップで作成したOracle Cloudアカウントのユーザー名およびトークン文字列に置き換えます:
    BEGIN
      DBMS_CLOUD.CREATE_CREDENTIAL(
        credential_name => 'ADB_OBJECTSTORE', 
        username => '<user-name>',
        password => '<token>'
      );
    END;
  4. ソース・データベースで次のスクリプトを実行して、データのエクスポート・ジョブを作成します。オブジェクト・ストアURIの<region><namespace>および<bucket-name>を適宜置き換えてください。SRC_OCIGGLL.dmpは、このスクリプトの実行時に作成されるファイルです。
    DECLARE
    ind NUMBER;              -- Loop index
    h1 NUMBER;               -- Data Pump job handle
    percent_done NUMBER;     -- Percentage of job complete
    job_state VARCHAR2(30);  -- To keep track of job state
    le ku$_LogEntry;         -- For WIP and error messages
    js ku$_JobStatus;        -- The job status from get_status
    jd ku$_JobDesc;          -- The job description from get_status
    sts ku$_Status;          -- The status object returned by get_status
    
    BEGIN
    -- Create a (user-named) Data Pump job to do a schema export.
    h1 := DBMS_DATAPUMP.OPEN('EXPORT','SCHEMA',NULL,'SRC_OCIGGLL_EXPORT','LATEST');
    
    -- Specify a single dump file for the job (using the handle just returned
    -- and a directory object, which must already be defined and accessible
    -- to the user running this procedure.
    DBMS_DATAPUMP.ADD_FILE(h1,'https://objectstorage.<region>.oraclecloud.com/n/<namespace>/b/<bucket-name>/o/SRC_OCIGGLL.dmp','ADB_OBJECTSTORE','100MB',DBMS_DATAPUMP.KU$_FILE_TYPE_URIDUMP_FILE,1);
    
    -- A metadata filter is used to specify the schema that will be exported.
    DBMS_DATAPUMP.METADATA_FILTER(h1,'SCHEMA_EXPR','IN (''SRC_OCIGGLL'')');
    
    -- Start the job. An exception will be generated if something is not set up properly.
    DBMS_DATAPUMP.START_JOB(h1);
    
    -- The export job should now be running. In the following loop, the job
    -- is monitored until it completes. In the meantime, progress information is displayed.
    percent_done := 0;
    job_state := 'UNDEFINED';
    while (job_state != 'COMPLETED') and (job_state != 'STOPPED') loop
      dbms_datapump.get_status(h1,dbms_datapump.ku$_status_job_error + dbms_datapump.ku$_status_job_status + dbms_datapump.ku$_status_wip,-1,job_state,sts);
      js := sts.job_status;
    
    -- If the percentage done changed, display the new value.
    if js.percent_done != percent_done
    then
      dbms_output.put_line('*** Job percent done = ' || to_char(js.percent_done));
      percent_done := js.percent_done;
    end if;
    
    -- If any work-in-progress (WIP) or error messages were received for the job, display them.
    if (bitand(sts.mask,dbms_datapump.ku$_status_wip) != 0)
    then
      le := sts.wip;
    else
      if (bitand(sts.mask,dbms_datapump.ku$_status_job_error) != 0)
      then
        le := sts.error;
      else
        le := null;
      end if;
    end if;
    if le is not null
    then
      ind := le.FIRST;
      while ind is not null loop
        dbms_output.put_line(le(ind).LogText);
        ind := le.NEXT(ind);
      end loop;
    end if;
      end loop;
    
      -- Indicate that the job finished and detach from it.
      dbms_output.put_line('Job has completed');
      dbms_output.put_line('Final job state = ' || job_state);
      dbms_datapump.detach(h1);
    END;

タスク5: Oracle Data Pump (ImpDP)を使用したターゲット・データベースのインスタンス化

Oracle Data Pump (ImpDP)を使用して、ソース・データベースからエクスポートしたSRC_OCIGGLL.dmpからターゲット・データベースにデータをインポートします。

  1. Oracle Object Storeにアクセスするための資格証明をターゲット・データベースに作成します(前述の項と同じ情報を使用します)。
    BEGIN
      DBMS_CLOUD.CREATE_CREDENTIAL( 
        credential_name => 'ADB_OBJECTSTORE',
        username => '<user-name>',
        password => '<token>'
      );
    END;
  2. ターゲット・データベースで次のスクリプトを実行して、SRC_OCIGGLL.dmpからデータをインポートします。オブジェクト・ストアURIの<region><namespace>および<bucket-name>を適宜置き換えてください:
    DECLARE
    ind NUMBER;  -- Loop index
    h1 NUMBER;  -- Data Pump job handle
    percent_done NUMBER;  -- Percentage of job complete
    job_state VARCHAR2(30);  -- To keep track of job state
    le ku$_LogEntry;  -- For WIP and error messages
    js ku$_JobStatus;  -- The job status from get_status
    jd ku$_JobDesc;  -- The job description from get_status
    sts ku$_Status;  -- The status object returned by get_status
    BEGIN
    
    -- Create a (user-named) Data Pump job to do a "full" import (everything
    -- in the dump file without filtering).
    h1 := DBMS_DATAPUMP.OPEN('IMPORT','FULL',NULL,'SRCMIRROR_OCIGGLL_IMPORT');
    
    -- Specify the single dump file for the job (using the handle just returned)
    -- and directory object, which must already be defined and accessible
    -- to the user running this procedure. This is the dump file created by
    -- the export operation in the first example.
    
    DBMS_DATAPUMP.ADD_FILE(h1,'https://objectstorage.<region>.oraclecloud.com/n/<namespace>/b/<bucket-name>/o/SRC_OCIGGLL.dmp','ADB_OBJECTSTORE',null,DBMS_DATAPUMP.KU$_FILE_TYPE_URIDUMP_FILE);
    
    
    -- A metadata remap will map all schema objects from SRC_OCIGGLL to SRCMIRROR_OCIGGLL.
    DBMS_DATAPUMP.METADATA_REMAP(h1,'REMAP_SCHEMA','SRC_OCIGGLL','SRCMIRROR_OCIGGLL');
    
    -- If a table already exists in the destination schema, skip it (leave
    -- the preexisting table alone). This is the default, but it does not hurt
    -- to specify it explicitly.
    DBMS_DATAPUMP.SET_PARAMETER(h1,'TABLE_EXISTS_ACTION','SKIP');
    
    -- Start the job. An exception is returned if something is not set up properly.
    DBMS_DATAPUMP.START_JOB(h1);
    
    -- The import job should now be running. In the following loop, the job is
    -- monitored until it completes. In the meantime, progress information is
    -- displayed. Note: this is identical to the export example.
    percent_done := 0;
    job_state := 'UNDEFINED';
    while (job_state != 'COMPLETED') and (job_state != 'STOPPED') loop
      dbms_datapump.get_status(h1,
        dbms_datapump.ku$_status_job_error +
        dbms_datapump.ku$_status_job_status +
        dbms_datapump.ku$_status_wip,-1,job_state,sts);
        js := sts.job_status;
    
      -- If the percentage done changed, display the new value.
      if js.percent_done != percent_done
      then
        dbms_output.put_line('*** Job percent done = ' ||
        to_char(js.percent_done));
        percent_done := js.percent_done;
      end if;
    
      -- If any work-in-progress (WIP) or Error messages were received for the job, display them.
      if (bitand(sts.mask,dbms_datapump.ku$_status_wip) != 0)
      then
        le := sts.wip;
      else
        if (bitand(sts.mask,dbms_datapump.ku$_status_job_error) != 0)
        then
          le := sts.error;
        else
          le := null;
        end if;
      end if;
      if le is not null
      then
        ind := le.FIRST;
        while ind is not null loop
          dbms_output.put_line(le(ind).LogText);
          ind := le.NEXT(ind);
        end loop;
      end if;
    end loop;
    
    -- Indicate that the job finished and gracefully detach from it.
    dbms_output.put_line('Job has completed');
    dbms_output.put_line('Final job state = ' || job_state);
    dbms_datapump.detach(h1);
    END;

タスク6: 非統合Replicatの追加および実行

  1. Replicatを追加して実行します
    1. 「パラメータ・ファイル」画面で、MAP *.*, TARGET *.*;を次のスクリプトに置き換えます:
      -- Capture DDL operations for listed schema tables
      --
      ddl include mapped
      --
      -- Add step-by-step history of ddl operations captured
      -- to the report file. Very useful when troubleshooting.
      --
      ddloptions report
      --
      -- Write capture stats per table to the report file daily.
      --
      report at 00:01
      --
      -- Rollover the report file weekly. Useful when PR runs
      -- without being stopped/started for long periods of time to
      -- keep the report files from becoming too large.
      --
      reportrollover at 00:01 on Sunday
      --
      -- Report total operations captured, and operations per second
      -- every 10 minutes.
      --
      reportcount every 10 minutes, rate
      --
      -- Table map list for apply
      --
      DBOPTIONS ENABLE_INSTANTIATION_FILTERING;
      MAP SRC_OCIGGLL.*, TARGET SRCMIRROR_OCIGGLL.*;

      ノート:

      DBOPTIONS ENABLE_INSTATIATION_FILTERINGによって、Oracle Data Pumpを使用してインポートした表に対するCSNフィルタリングが可能になります。詳細は、DBOPTIONSのリファレンスを参照してください。
  2. データベースAでいくつかの変更を実行して、データベースBにレプリケートされることを確認します。

タスク7: データベースBからデータベースAへのレプリケーションの構成

タスク1から6では、データベースAからデータベースBへのレプリケーションを確立しました。次のステップでは、データベースBからデータベースAへのレプリケーションを設定します。

  1. データベースBでExtractを追加して実行します。「Extractパラメータ」ページで、EXTRAIL <extract-name>の後に次が含まれていることを確認します:
    -- Table list for capture
    table SRCMIRROR_OCIGGLL.*;
    
    -- Exclude changes made by GGADMIN
    tranlogoptions excludeuser ggadmin
  2. データベースAでReplicatを追加して実行します。「パラメータ」ページで、MAP *.*, TARGET *.*;を次に置き換えます:
    MAP SRCMIRROR_OCIGGLL.*, TARGET SRC_OCIGGLL.*;
  3. データベースBでいくつかの変更を実行して、データベースAにレプリケートされることを確認します。

タスク8: プロセスのモニターおよびメンテナンス

  1. パフォーマンスをモニターします
  2. トレイル・ファイルを管理します