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

参考文献

環境

DBの構成

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

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

レプリケーション対象

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

#pre{{

方針

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

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

マスター・サイトの設定

SDB1.sugimura.cc の設定

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

#pre{{

#pre{{

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 の設定

SDB1 とほぼ同じです。

#pre{{

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 }}

スケジュール・リンクの作成

#pre{{

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

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

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; /

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 }}

マスター・グループの設定

マスター・グループの作成

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

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

#pre{{ conn repadmin/repadmin@SDB1.sugimura.cc

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

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

#pre{{ conn repadmin/repadmin@SDB1.sugimura.cc

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; / }}

マスター・サイトの追加

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

#pre{{ conn repadmin/repadmin@SDB1.sugimura.cc

追加されたことを確認

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

#pre{{

GNAME DBLINK MAS


SCOTT_REPG SDB1.SUGIMURA.CC Y SCOTT_REPG SDB2.SUGIMURA.CC N

SQL> }}

レプリケーション・サポートを生成

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

#pre{{ 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; / }}

レプリケーション開始前の確認

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

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

 COUNT(*)

       19

SQL> }}

詳しく見てみます。

#pre{{ 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にして上げ直します。

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

 COUNT(*)

       11

SQL> }}

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

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

#pre{{ 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> }}

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

#pre{{ 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 でも追加しておいたほうがいいのかなということで、 こちらでも。

#pre{{ 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> }}

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

#pre{{ conn repadmin/repadmin@SDB1.sugimura.cc

BEGIN

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

END; / }}

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

#pre{{ 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> }}

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

#pre{{

BEGIN

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

END; /

BEGIN

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

END; / }}

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

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

 COUNT(*)

        0

SQL> }}

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

レプリケーションを開始

#pre{{ conn repadmin/repadmin@SDB1.sugimura.cc

BEGIN

  DBMS_REPCAT.RESUME_MASTER_ACTIVITY (
     gname => 'scott_repg');

END; / }}

動作確認

SDB1 → SDB2

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

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

1行が作成されました。

SQL> commit;

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

SQL> }}

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

#pre{{ 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

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

#pre{{ 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 で確認してみます。

#pre{{ 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> }}

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

管理

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



トップ   差分 履歴 リロード   一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2011-01-29 (土) 15:27:49