前回で事前準備を行ったので、今回はパラメータ設定と、実際に競合を発生させて結果を確認してゆきます。
まず、レプリケートのループを回避する設定を入れます。これをやらないと一方の更新が他方に同期され、その同期された更新が再び元のDBに同期され…となって、永久ループに陥ってしまいます。
具体的にはREPLICATのパラメータでタグを設定します。「00」はデフォルトのタグ名です。
DBOPTIONS SETTAG 00
EXTRACTのパラメータでタグ付きのレコードを除外する設定を行います。
TRANLOGOPTIONS EXCLUDETAG 00
次に、競合解消方法をパターンごとにREPLICATのパラメータで指定します。
今回は設定例(1)として、Golden Gateのマニュアルに載っていた例をそのまま使用します。
レプリケート先のグループ名はrepg2、レプリケート元はrepg4で、それ以外は同じ内容をレプリケート元と先で設定します。
$ cat repg2.prm
REPLICAT repg2
DBOPTIONS SETTAG 00
DBLOGIN USERID ggadmin,password welcome1
ASSUMETARGETDEFS
MAP ggtest.TAB2, TARGET ggtest.TAB2, MAPINVISIBLECOLUMNS,
COMPARECOLS (ON UPDATE ALL, ON DELETE ALL),
RESOLVECONFLICT (UPDATEROWEXISTS, (DEFAULT, USEMAX (CDRTS$ROW))),
RESOLVECONFLICT (INSERTROWEXISTS, (DEFAULT, USEMAX (CDRTS$ROW))),
RESOLVECONFLICT (DELETEROWEXISTS, (DEFAULT, OVERWRITE)),
RESOLVECONFLICT (UPDATEROWMISSING, (DEFAULT, OVERWRITE)),
RESOLVECONFLICT (DELETEROWMISSING, (DEFAULT, DISCARD));
設定例(1)のMAP文の説明は以下の通りです。
- INSERTROWEXISTS競合には、USEMAX解決を使用する。つまり、挿入時に行が存在する場合は、last_mod_time列を解決列として使用し、証跡の値とデータベースの値のどちらが大きいかを判別する。証跡の値の方が大きい場合、レコードを適用するが、挿入を更新に変更する。データベースの値の方が大きい場合、レコードを無視する。
- UPDATEROWEXISTS競合には、USEMAX解決を使用する。つまり、更新時に行が存在する場合は、last_mod_time列を解決列として使用する。証跡の値の方が大きい場合、更新を適用する。
- USEMINとUSEMAXを使用し、値がまったく同じ場合、RESOLVECONFLICTはトリガーされず、受け取った行は無視される。USEMINEQとUSEMAXEQを使用し、値がまったく同じ場合、解決策はトリガーされる。
- DELETEROWEXISTS競合には、OVERWRITE解決を使用する。つまり、削除操作時に行が存在する場合は、削除を適用する。
- UPDATEROWMISSING競合には、OVERWRITE解決を使用する。つまり、更新時に行が存在しない場合は、更新を挿入に変更して適用する。
- DELETROWMISSING競合には、DISCARD解決を使用する。つまり、削除操作時に行が存在しない場合は、証跡レコードを破棄する。
更にレプリケート元の設定を続けます。
EXTRACTパラメータ
$ cat extg2.prm
EXTRACT extg2
TRANLOGOPTIONS EXCLUDETAG 00
USERID ggadmin,password welcome1
EXTTRAIL /u01/app/oracle/ogg_1/dirdat/stod/l2
TABLE GGTEST.TAB2;
データポンプEXTRACTパラメータ
$ cat dpg2.prm
EXTRACT dpg2
USERID ggadmin,password welcome1
RMTHOST mitsdb01, MGRPORT 31003
RMTTRAIL /u01/app/oracle/ogg_2/dirdat/stod/r2
TABLE GGTEST.TAB2;
レプリケート先の設定は以下の通りです。
EXTRACTパラメータ
$ cat extg4.prm
EXTRACT extg4
TRANLOGOPTIONS EXCLUDETAG 00
USERID ggadmin,password welcome1
EXTTRAIL /u01/app/oracle/ogg_2/dirdat/dtos/l4
TABLE GGTEST.TAB2;
データポンプEXTRACTパラメータ
$ cat dpg4.prm
EXTRACT dpg4
USERID ggadmin,password welcome1
RMTHOST mitsdb01, MGRPORT 31002
RMTTRAIL /u01/app/oracle/ogg_1/dirdat/dtos/r4
TABLE GGTEST.TAB2;
パラメータファイルの設定が終わったので、両データベースにそれぞれ接続し、以下を実行します。
レプリケート元
Extractの登録
REGISTER EXTRACT extg2 DATABASE
プライマリExtractの追加
ADD EXTRACT extg2, INTEGRATED TRANLOG, BEGIN NOW
ローカル証跡の追加
ADD EXTTRAIL /u01/app/oracle/ogg_1/dirdat/stod/l2, EXTRACT extg2
データ・ポンプExtractグループの追加
ADD EXTRACT dpg2,EXTTRAILSOURCE /u01/app/oracle/ogg_1/dirdat/stod/l2
リモート証跡の追加
ADD RMTTRAIL /u01/app/oracle/ogg_2/dirdat/stod/r2,EXTRACT dpg2
Replicatグループの追加
チェックポイント表の作成
ADD CHECKPOINTTABLE ggadmin.chktbl
ADD REPLICAT repg4, EXTTRAIL /u01/app/oracle/ogg_2/dirdat/stod/r4,CHECKPOINTTABLE ggadmin.chktbl
レプリケート先
Extractの登録
REGISTER EXTRACT extg4 DATABASE
プライマリExtractの追加
ADD EXTRACT extg4, INTEGRATED TRANLOG, BEGIN NOW
ローカル証跡の追加
ADD EXTTRAIL /u01/app/oracle/ogg_2/dirdat/dtos/l4, EXTRACT extg4
データ・ポンプExtractグループの追加
ADD EXTRACT dpg4,EXTTRAILSOURCE /u01/app/oracle/ogg_2/dirdat/dtos/l4
リモート証跡の追加
ADD RMTTRAIL /u01/app/oracle/ogg_1/dirdat/dtos/r2,EXTRACT dpg4
Replicatグループの追加
ADD REPLICAT repg2, EXTTRAIL /u01/app/oracle/ogg_1/dirdat/dtos/r2,CHECKPOINTTABLE ggadmin.chktbl
まず、レプリケート先でデータを挿入し、結果を確認します。
SQL> insert into tab2 values(1,'ggd',systimestamp);
1 row created.
SQL> select * from tab2;
COL1 COL2 COL3
---------- ---------- ----------------------------------------
1 ggd 25-MAR-22 11.37.23.635009 AM
レプリケート元でも同じキーでデータを挿入します。
SQL> insert into tab2 values(1,'ggs',systimestamp);
1 row created.
SQL> select * from tab2;
COL1 COL2 COL3
---------- ---------- ----------------------------------------
1 ggs 25-MAR-22 11.37.36.913159 AM
この後、双方でcommitを実行し、数秒待ってデータを確認します。
レプリケート元
SQL> select * from tab2;
COL1 COL2 COL3
---------- ---------- ----------------------------------------
1 ggs 25-MAR-22 11.37.36.913159 AM
レプリケート先
SQL> select * from tab2;
COL1 COL2 COL3
---------- ---------- ----------------------------------------
1 ggs 25-MAR-22 11.37.36.913159 AM
レプリケート元の方が後からinsertされたので、レプリケート元のデータで上書きされています。これはまあ、想定通りと言うか、当然の結果ですね。
次にupdateとdeleteの競合テストを行います。
レプリケート元でupdateを発行します。
SQL> update tab2 set col2='ggsggs' where col1=1;
1 row updated.
SQL> select * from tab2;
COL1 COL2 COL3
---------- ---------- ----------------------------------------
1 ggsggs 25-MAR-22 11.37.36.913159 AM
レプリケート先で同じレコードを削除します。
双方でcommit発行して、数秒後に確認します。
レプリケート元
SQL> select * from tab2;
no rows selected
レプリケート先
SQL> select * from tab2;
COL1 COL2 COL3
---------- ---------- ----------------------------------------
1 ggsggs 25-MAR-22 11.37.36.913159 AM
レプリケート元では更新した行が無くなってしまい、レプリケート先では削除した行が復活してレプリケート元の更新内容が反映されています。
これはどういう事かと言うと
- updateした側は、相手側のdelete情報が来た時、削除を適用するので削除される
- 削除した側は相手側のupdate情報が送られて来た時、OVERWRITE解決するので相手側のupdate後の状態になる(レコードが復活する)
なので仕様通りと言うか、設定どおりです。
でもレプリケート元と先でデータが一致していないので、ちょっと想定外と言いますか、期待と違ってしまいました…。
なので次回は設定例(2)を検証してみます。