Front page   Edit Freeze Diff Upload Copy Rename Reload   New List of pages Search Recent changes   Help   RSS of recent changes

技術文書/Oracle/マルチマスタレプリケーション

Last-modified: Sat, 29 Jan 2011 15:27:49 JST (4322d)
Top > 技術文書 > Oracle > マルチマスタレプリケーション

2つのDBでマルチマスタレプリケーションしてみました。

参考文献 EditEdit(GUI)

環境 EditEdit(GUI)

  • Solaris 10 (x64_64)
  • Oracle Database 10g R2

DBの構成 EditEdit(GUI)

  • SDB1 (service_names=SDB1.sugimura.cc)
  • SDB2 (service_names=SDB2.sugimura.cc)

2つDBを作成して、この間で互いにレプリケーションしてみます。

Net Services の設定をして、それぞれこの名前でつながるようにしておきます。

レプリケーション対象 EditEdit(GUI)

  • SCOTTスキーマの4つの表
    • DEPT
    • EMP
    • BONUS
    • SALGRADE

入っていなければ、$ORACLE_HOME/rdbms/admin/utlsampl.sql からインストールしておきます。

-bash-3.00$ export ORACLE_SID=SDB1
-bash-3.00$ sqlplus / as sysdba @?/rdbms/admin/utlsampl
-bash-3.00$ export ORACLE_SID=SDB2
-bash-3.00$ sqlplus / as sysdba @?/rdbms/admin/utlsampl

方針 EditEdit(GUI)

MVIEW も使わず、最も簡単な構成で進めました。

  • マスター・サイトの設定
  • マスター・グループの設定

基本的にはマニュアルに従うだけです。

マスター・サイトの設定 EditEdit(GUI)

SDB1.sugimura.cc の設定 EditEdit(GUI)

sdb1.sql を下記のように書いて、sqlplus から流します。

-bash-3.00$ sqlplus /nolog @sdb1.sql
-bash-3.00$ cat sdb1.sql
spool sdb1.log

connect system/oracle@sdb1.sugimura.cc

CREATE USER repadmin IDENTIFIED BY repadmin;
BEGIN
   DBMS_REPCAT_ADMIN.GRANT_ADMIN_ANY_SCHEMA (
      username => 'repadmin');
END;
/

GRANT COMMENT ANY TABLE TO repadmin;
GRANT LOCK ANY TABLE TO repadmin;
GRANT SELECT ANY DICTIONARY TO repadmin;

BEGIN
   DBMS_DEFER_SYS.REGISTER_PROPAGATOR (
      username => 'repadmin');
END;
/

BEGIN
   DBMS_REPCAT_ADMIN.REGISTER_USER_REPGROUP (
      username => 'repadmin',
      privilege_type => 'receiver',
      list_of_gnames => NULL);
END;
/

CONNECT repadmin/repadmin@sdb1.sugimura.cc

BEGIN
   DBMS_DEFER_SYS.SCHEDULE_PURGE (
      next_date => SYSDATE,
      interval => 'SYSDATE + 1/24',
      delay_seconds => 0);
END;
/

spool off
quit

SDB2.sugimura.cc の設定 EditEdit(GUI)

SDB1 とほぼ同じです。

-bash-3.00$ cat sdb2.sql 
spool sdb2.log

conn system/oracle@sdb2.sugimura.cc

CREATE USER repadmin IDENTIFIED BY repadmin;

BEGIN
   DBMS_REPCAT_ADMIN.GRANT_ADMIN_ANY_SCHEMA (
      username => 'repadmin');
END;
/

GRANT COMMENT ANY TABLE TO repadmin;
GRANT LOCK ANY TABLE TO repadmin;
GRANT SELECT ANY DICTIONARY TO repadmin;

BEGIN
   DBMS_DEFER_SYS.REGISTER_PROPAGATOR (
      username => 'repadmin');
END;
/

BEGIN
   DBMS_REPCAT_ADMIN.REGISTER_USER_REPGROUP (
      username => 'repadmin',
      privilege_type => 'receiver',
      list_of_gnames => NULL);
END;
/

CONNECT repadmin/repadmin@sdb2.sugimura.cc

BEGIN
   DBMS_DEFER_SYS.SCHEDULE_PURGE (
      next_date => SYSDATE,
      interval => 'SYSDATE + 1/24',
      delay_seconds => 0);
END;
/

spool off
quit

スケジュール・リンクの作成 EditEdit(GUI)

-bash-3.00$ cat dblink.sql
spool dblink.log

-- dblink: sdb1.sugimura.cc
conn system/oracle@sdb1.sugimura.cc
create public database link sdb2.sugimura.cc using 'sdb2.sugimura.cc';

conn repadmin/repadmin@sdb1.sugimura.cc
create database link sdb2.sugimura.cc connect to repadmin identified by repadmin;

-- dblink: sdb2.sugimura.cc
conn system/oracle@sdb2.sugimura.cc
create public database link sdb1.sugimura.cc using 'sdb1.sugimura.cc';

conn repadmin/repadmin@sdb2.sugimura.cc
create database link sdb1.sugimura.cc connect to repadmin identified by repadmin;

-- schedule: sdb1.sugimura.cc
conn repadmin/repadmin@sdb1.sugimura.cc

BEGIN
   DBMS_DEFER_SYS.SCHEDULE_PUSH (
      destination => 'sdb2.sugimura.cc',
      interval => 'SYSDATE + (1/144)',
      next_date => SYSDATE,
      parallelism => 1,
      execution_seconds => 1500,
      delay_seconds => 1200);
END;
/

-- schedule: sdb2.sugimura.cc
conn repadmin/repadmin@sdb2.sugimura.cc

BEGIN
   DBMS_DEFER_SYS.SCHEDULE_PUSH (
      destination => 'sdb1.sugimura.cc',
      interval => 'SYSDATE + (1/144)',
      next_date => SYSDATE,
      parallelism => 1,
      execution_seconds => 1500,
      delay_seconds => 1200);
END;
/

spool off
quit

マスター・グループの設定 EditEdit(GUI)

マスター・グループの作成 EditEdit(GUI)

マスター・グループを作成したサイトが 「マスター定義サイト」となります。 SDB1 をマスター定義サイトとします。

scott_repg という名前にしました。

conn repadmin/repadmin@SDB1.sugimura.cc

-- repgroup
BEGIN
   DBMS_REPCAT.CREATE_MASTER_REPGROUP (
      gname => 'scott_repg');
END;
/

オブジェクトをマスター・グループに追加 EditEdit(GUI)

scott_repg に4つの表を追加します。

conn repadmin/repadmin@SDB1.sugimura.cc

-- object
BEGIN
   DBMS_REPCAT.CREATE_MASTER_REPOBJECT (
      gname => 'scott_repg',
      type => 'TABLE',
      oname => 'dept',
      sname => 'scott',
      use_existing_object => TRUE,
      copy_rows => FALSE);
END;
/

BEGIN
   DBMS_REPCAT.CREATE_MASTER_REPOBJECT (
      gname => 'scott_repg',
      type => 'TABLE',
      oname => 'emp',
      sname => 'scott',
      use_existing_object => TRUE,
      copy_rows => FALSE);
END;
/

BEGIN
   DBMS_REPCAT.CREATE_MASTER_REPOBJECT (
      gname => 'scott_repg',
      type => 'TABLE',
      oname => 'bonus',
      sname => 'scott',
      use_existing_object => TRUE,
      copy_rows => FALSE);
END;
/

BEGIN
   DBMS_REPCAT.CREATE_MASTER_REPOBJECT (
      gname => 'scott_repg',
      type => 'TABLE',
      oname => 'salgrade',
      sname => 'scott',
      use_existing_object => TRUE,
      copy_rows => FALSE);
END;
/

マスター・サイトの追加 EditEdit(GUI)

レプリケーション先である SDB2 を追加します。

conn repadmin/repadmin@SDB1.sugimura.cc

-- master site
BEGIN
   DBMS_REPCAT.ADD_MASTER_DATABASE (
      gname => 'scott_repg',
      master => 'sdb2.sugimura.cc',
      use_existing_objects => TRUE,
      copy_rows => FALSE,
      propagation_mode => 'ASYNCHRONOUS');
END;
/

追加されたことを確認 EditEdit(GUI)

dba_repsites で設定を確認します。SDB2 があればOKです。

-bash-3.00$ sqlplus repadmin/repadmin@SDB1.sugimura.cc
...
SQL> 
SQL> col gname format a10
SQL> col dblink format a20
SQL> select gname, dblink, masterdef from dba_repsites;

GNAME      DBLINK               MAS
---------- -------------------- ---
SCOTT_REPG SDB1.SUGIMURA.CC     Y
SCOTT_REPG SDB2.SUGIMURA.CC     N

SQL> 

レプリケーション・サポートを生成 EditEdit(GUI)

必要なパッケージやトリガーを作るようです。

conn repadmin/repadmin@SDB1.sugimura.cc

BEGIN
    DBMS_REPCAT.GENERATE_REPLICATION_SUPPORT (
      sname => 'scott',
      oname => 'dept',
      type => 'TABLE',
      min_communication => TRUE);
END;
/

BEGIN
    DBMS_REPCAT.GENERATE_REPLICATION_SUPPORT (
      sname => 'scott',
      oname => 'emp',
      type => 'TABLE',
      min_communication => TRUE);
END;

/
BEGIN
    DBMS_REPCAT.GENERATE_REPLICATION_SUPPORT (
      sname => 'scott',
      oname => 'bonus',
      type => 'TABLE',
      min_communication => TRUE);
END;
/

BEGIN
    DBMS_REPCAT.GENERATE_REPLICATION_SUPPORT (
      sname => 'scott',
      oname => 'salgrade',
      type => 'TABLE',
      min_communication => TRUE);
END;
/

レプリケーション開始前の確認 EditEdit(GUI)

dba_repcatlog が空になると始められるとのことですが、 このような状態になってしまいました。

SQL> select count(*) from dba_repcatlog where gname = 'SCOTT_REPG';

  COUNT(*)
----------
        19

SQL> 

詳しく見てみます。

SQL> col status format a20
SQL> col sname format a10
SQL> col oname format a10
SQL> select status, sname, oname from dba_repcatlog where gname = 'SCOTT_REPG';

STATUS               SNAME      ONAME
-------------------- ---------- ----------
AWAIT_CALLBACK       SCOTT      DEPT
READY                SCOTT      DEPT
AWAIT_CALLBACK
AWAIT_CALLBACK       SCOTT      DEPT
AWAIT_CALLBACK       SCOTT      BONUS
AWAIT_CALLBACK       SCOTT      SALGRADE
AWAIT_CALLBACK       SCOTT      EMP
AWAIT_CALLBACK       SCOTT_REPG -1
READY                SCOTT_REPG -1
READY                SCOTT      DEPT
READY                SCOTT      EMP

STATUS               SNAME      ONAME
-------------------- ---------- ----------
AWAIT_CALLBACK       SCOTT      EMP
READY                SCOTT      EMP
READY                SCOTT      BONUS
AWAIT_CALLBACK       SCOTT      BONUS
READY                SCOTT      BONUS
READY                SCOTT      SALGRADE
AWAIT_CALLBACK       SCOTT      SALGRADE
READY                SCOTT      SALGRADE

19行が選択されました。

SQL> 

初期化パラメータ job_queue_processes が 0 になっていたのが原因でした。 2サイトあるので、2にして上げ直します。

SQL> select count(*) from dba_repcatlog where gname = 'SCOTT_REPG';

  COUNT(*)
----------
        11

SQL> 

減りましたが0にはなりません。

STATUS が ERROR となっている行がありました。

SQL> select status, message from dba_repcatlog where gname = 'SCOTT_REPG';

STATUS
------------------------------------------
MESSAGE
--------------------------------------------------------------------------------
ERROR
ORA-23416: 表"SCOTT"."BONUS"に主キー制約がありません。

ERROR
ORA-23416: 表"SCOTT"."BONUS"に主キー制約がありません。

ERROR
ORA-23416: 表"SCOTT"."SALGRADE"に主キー制約がありません。


STATUS
------------------------------------------
MESSAGE
--------------------------------------------------------------------------------
ERROR
ORA-23416: 表"SCOTT"."SALGRADE"に主キー制約がありません。


SQL> 

そうですか、というわけで制約を追加します。

SQL> conn scott/tiger@SDB1
接続されました。
SQL> alter table bonus add constraint bonus_pk primary key (ename, job);

表が変更されました。

SQL> alter table salgrade add constraint salgrade_pk primary key (grade);

表が変更されました。

SQL> 

SDB2 でも追加しておいたほうがいいのかなということで、 こちらでも。

SQL> conn scott/tiger@SDB2
接続されました。
SQL> alter table bonus add constraint bonus_pk primary key (ename, job);

表が変更されました。

SQL> alter table salgrade add constraint salgrade_pk primary key (grade);

表が変更されました。

SQL> 

作り直すため、オブジェクトを消します。

conn repadmin/repadmin@SDB1.sugimura.cc

-- drop
BEGIN
   DBMS_REPCAT.DROP_MASTER_REPOBJECT (
      type => 'TABLE',
      oname => 'bonus',
      sname => 'scott');
END;
/

BEGIN
   DBMS_REPCAT.DROP_MASTER_REPOBJECT (
      type => 'TABLE',
      oname => 'salgrade',
      sname => 'scott');
END;
/

オブジェクトを消したらログも消します。

SQL> exec dbms_repcat.purge_master_log( id=>NULL, source=>NULL, gname=>'SCOTT_REPG');

PL/SQLプロシージャが正常に完了しました。

SQL> 
SQL> select count(*) from dba_repcatlog where gname = 'SCOTT_REPG';

  COUNT(*)
----------
         0

SQL> 

まっさらにしたので、また作り直します。

-- create
BEGIN
   DBMS_REPCAT.CREATE_MASTER_REPOBJECT (
      gname => 'scott_repg',
      type => 'TABLE',
      oname => 'bonus',
      sname => 'scott',
      use_existing_object => TRUE,
      copy_rows => FALSE);
END;
/

BEGIN
   DBMS_REPCAT.CREATE_MASTER_REPOBJECT (
      gname => 'scott_repg',
      type => 'TABLE',
      oname => 'salgrade',
      sname => 'scott',
      use_existing_object => TRUE,
      copy_rows => FALSE);
END;
/

-- support
BEGIN
    DBMS_REPCAT.GENERATE_REPLICATION_SUPPORT (
      sname => 'scott',
      oname => 'bonus',
      type => 'TABLE',
      min_communication => TRUE);
END;
/

BEGIN
    DBMS_REPCAT.GENERATE_REPLICATION_SUPPORT (
      sname => 'scott',
      oname => 'salgrade',
      type => 'TABLE',
      min_communication => TRUE);
END;
/

再度 dba_repcatlog を確認してみます。

SQL> select count(*) from dba_repcatlog where gname = 'SCOTT_REPG';

  COUNT(*)
----------
         0

SQL> 

ようやくこれで準備完了です。

レプリケーションを開始 EditEdit(GUI)

conn repadmin/repadmin@SDB1.sugimura.cc

BEGIN
   DBMS_REPCAT.RESUME_MASTER_ACTIVITY (
      gname => 'scott_repg');
END;
/

動作確認 EditEdit(GUI)

SDB1 → SDB2 EditEdit(GUI)

DEPT表に1行追加してみます。

SQL> conn scott/tiger@sdb1
接続されました。
SQL> insert into dept values (50, 'WORK1', 'TOKYO');

1行が作成されました。

SQL> commit;

コミットが完了しました。

SQL> 

しばらくしてから SDB2 で見てみます。

SQL> conn scott/tiger@sdb2
接続されました。
SQL> set lines 1000  
SQL> select * from dept; 

    DEPTNO DNAME                                      LOC
---------- ------------------------------------------ ---------------------------------------
        10 ACCOUNTING                                 NEW YORK
        20 RESEARCH                                   DALLAS
        30 SALES                                      CHICAGO
        40 OPERATIONS                                 BOSTON
        50 WORK1                                      TOKYO

SQL> 

SDB1 で追加した行が SDB2 に反映されました。

SDB2 → SDB1 EditEdit(GUI)

今度は SALGRADE 表から1行消してみます。

SQL> conn scott/tiger@sdb2
接続されました。
SQL> select * from salgrade;

     GRADE      LOSAL      HISAL
---------- ---------- ----------
         1        700       1200
         2       1201       1400
         3       1401       2000
         4       2001       3000
         5       3001       9999

SQL> delete from salgrade where grade = 3;

1行が削除されました。

SQL> commit;

コミットが完了しました。

SQL> select * from salgrade;

     GRADE      LOSAL      HISAL
---------- ---------- ----------
         1        700       1200
         2       1201       1400
         4       2001       3000
         5       3001       9999

SQL> 

SDB1 で確認してみます。

SQL> conn scott/tiger@sdb1
接続されました。
SQL> select * from salgrade;

     GRADE      LOSAL      HISAL
---------- ---------- ----------
         1        700       1200
         2       1201       1400
         4       2001       3000
         5       3001       9999

SQL> 

ちゃんと反映されています。

管理 EditEdit(GUI)

マスター・サイトの追加や削除など、 管理については別ページにしました。



URL B I U SIZE Black Maroon Green Olive Navy Purple Teal Gray Silver Red Lime Yellow Blue Fuchsia Aqua White