前回の記事 STEP4 Oracle Golden Gate を使ってみる
ローカルの仮想環境に Oracle Golden Gate の環境を構築し、シンプルな同期処理が可能であることは確認できましたが、どこまで柔軟な同期処理が出来るのか、今回は実験的に以下のような同期処理が可能であるかを確認してみます。
ケース:ターゲット側にオートインクリメントのカラムがある場合、同期処理時にターゲット側で番号を採番させることは可能か?
Oracle Golden Gate を試してみる手順
1.サービスの起動など
2.テスト用テーブルの設計
3.テスト用テーブルの作成
4.Oracle Golden Gate の設定、各プロセス開始
5.同期テスト
1.サービスの起動など(ソース側、ターゲット側両方で実行する)
Listener や Oracleインスタンスが仮想環境の起動時にスタートアップする設定になっていない場合、仮想環境を起動する度にスタートしてあげる必要があります。
この作業はソース、ターゲット両方の仮想環境で実行します。
# ソース側
vagrant ssh myora1
# ターゲット側
vagrant ssh myora2
# ユーザ変更
$ sudo su - oracle
# Listener起動
$ lsnrctl start LISTENER
# Oracleインスタンス 起動
$ sql / as sysdba
SQL> startup
# PDB open
SQL> alter pluggable database all open;
SQL> exit
2.テスト用テーブルの設計
今回は以下のようなテーブルを用意したいと思います。
ソース側とターゲット側のテーブル構成はほとんど同じで、主な違いは2点で、テーブル名が違うことと、主キーである order_id カラムがターゲット側ではオートインクリメントのカラムとして定義します。
Oracle Golden Gate で同期処理を行う時に、オートインクリメントのカラムが機能するのかどうかを確かめます。
ソース側 テーブル名: ORDER_X
カラム名 | データ型 | 説明 |
---|---|---|
order_id | NUMBER | このテーブルの主キーで注文をユニークに管理する |
item_id | NUMBER | 注文を受け付けた商品のID |
units | NUMBER | 注文を受け付けた商品の数 |
created_at | DATE | 注文を受け付けた日時 |
updated_at | DATE | 注文を更新した日時。現在時刻を DEFAULT 値とする |
version | NUMBER | このレコードが更新された回数。登録時は1で更新される度に1ずつ増える |
num_sync | NUMBER | 同期処理が行われた回数。登録時は0で、同期される度に1ずつ増える |
ターゲット側 テーブル名: ORDER_Y
カラム名 | データ型 | 説明 |
---|---|---|
order_id | AUTO_INCREMENT | オートインクリメント。このテーブルの主キーで注文をユニークに管理する |
item_id | NUMBER | 注文を受け付けた商品のID |
units | NUMBER | 注文を受け付けた商品の数 |
created_at | DATE | 注文を受け付けた日時 |
updated_at | DATE | 注文を更新した日時 |
version | NUMBER | このレコードが更新された回数。登録時は1で更新される度に1ずつ増える |
num_sync | NUMBER | 同期処理が行われた回数。登録時は0で、同期される度に1ずつ増える |
3.テスト用テーブルの作成
# Oracle PDB ログイン
$ sql c##gguser/oracle@//localhost:1521/ORCLPDB1
SQL> CREATE TABLE ORDER_X (order_id NUMBER, item_id NUMBER, units NUMBER, created_at DATE, updated_at DATE, version NUMBER, num_sync NUMBER, primary key(order_id));
Table created.
SQL> DESC ORDER_X;
Name Null? Type
----------------------------------------- -------- ----------------------------
ORDER_ID NUMBER
ITEM_ID NUMBER
UNITS NUMBER
CREATED_AT DATE
UPDATED_AT DATE
VERSION NUMBER
NUM_SYNC NUMBER
SQL> exit
# Oracle PDB ログイン
$ sql c##gguser/oracle@//localhost:1521/ORCLPDB1
SQL> CREATE TABLE ORDER_Y (order_id NUMBER GENERATED BY DEFAULT AS IDENTITY, item_id NUMBER, units NUMBER, created_at DATE, updated_at DATE, version NUMBER, num_sync NUMBER, primary key(order_id));
Table created.
SQL> alter table ORDER_Y add constraint ORDER_Y_PK primary key (ORDER_ID);
SQL> DESC ORDER_Y;
Name Null? Type
----------------------------------------- -------- ----------------------------
ORDER_ID NOT NULL NUMBER
ITEM_ID NUMBER
UNITS NUMBER
CREATED_AT DATE
UPDATED_AT DATE
VERSION NUMBER
NUM_SYNC NUMBER
SQL> select constraint_name, constraint_type from user_constraints where table_name = 'ORDER_Y';
CONSTRAINT_NAME CONSTRAINT_TYPE
SYS_C007567 C
ORDER_Y_PK P
SQL> exit
ORDER_Y テーブル側の ORDER_ID はオートインクリメントのため、NOT NULL 制約が自動的に付与されています。
4.Oracle Golden Gate の設定、各プロセス開始
# ggsci 起動
$ /gg/ggsci
# repli2 編集
GGSCI (myora2) x> edit params repli2
# 以下のように設定する
REPLICAT repli2
USERID c##gguser@ORCLPDB1, PASSWORD oracle
MAP ORCLPDB1.c##gguser.ORDER_X, TARGET ORCLPDB1.c##gguser.ORDER_Y COLMAP(ITEM_ID=ITEM_ID, UNITS=UNITS, CREATED_AT=CREATED_AT, UPDATED_AT=UPDATED_AT, VERSION=VERSION, NUM_SYNC=@COMPUTE(NUM_SYNC + 1));
ORDER_X から ORDER_Y に同期させるようにマッピングしています。
ORDER_ID 以外のカラムを明示的にマッピングしています。ORDER_ID 以外のカラムが同期され、ORDER_ID カラムは自動採番にて値が入るようになることを期待しています。
また、NUM_SYNC のカラムには、元の値に1を加算した値が入ることを期待しています。
では、ターゲット側の Golden Gate のプロセスを起動していきます。
# Manager 起動
GGSCI (myora2) x> start manager
Manager started.
# Replicat 起動
GGSCI (myora2) x> start repli2
# 起動プロセス確認
GGSCI (myora2) x> info all
Program Status Group Lag at Chkpt Time Since Chkpt
MANAGER RUNNING
REPLICAT RUNNING REPLI2 00:00:00 187:31:09
# 終了
exit
ソース側の Golden Gate のプロセスを起動していきます。
# ggsci 起動
$ /gg/ggsci
# Manager 起動
GGSCI (myora1) x> start manager
Manager started.
# Capture 起動
GGSCI (myora1) x> start capture1
# Pump 起動
GGSCI (myora1) x> start pump1
# 起動プロセス確認
GGSCI (myora1) x> info all
Program Status Group Lag at Chkpt Time Since Chkpt
MANAGER RUNNING
EXTRACT RUNNING CAPTURE1 00:00:00 187:31:56
EXTRACT RUNNING PUMP1 00:00:00 187:33:13
# 終了
exit
5.同期テスト
それではソース側のテーブルにデータを挿入し、ターゲット側に同期されるかを確認していきます。
# Oracle PDB ログイン
$ sql c##gguser/oracle@//localhost:1521/ORCLPDB1
SQL> SELECT * FROM ORDER_X WHERE ORDER_ID = 100;
no rows selected
SQL> INSERT INTO ORDER_X (ORDER_ID, ITEM_ID, UNITS, CREATED_AT, UPDATED_AT, VERSION, NUM_SYNC) VALUES (100, 200, 3, sysdate, sysdate, 1, 0);
1 row created.
SQL> commit;
Commit complete.
SQL> SELECT * FROM ORDER_X WHERE ORDER_ID = 100;
ORDER_ID ITEM_ID UNITS CREATED_AT UPDATED_AT VERSION NUM_SYNC
100 200 3 19-SEP-21 19-SEP-21 1 0
# Oracle PDB ログイン
$ sql c##gguser/oracle@//localhost:1521/ORCLPDB1
SQL> SELECT * FROM ORDER_Y;
no rows selected
残念ながら同期処理はされていませんでした。
ログを確認してみると、"ORDER_ID is missing" という ERROR が発生しています。
つまり、"ORDER_ID" もマッピングしなければならないようです。
$ /gg/ggserr.log
ERROR OGG-00918 Oracle GoldenGate Delivery for Oracle, repli2.prm: Key column ORDER_ID is missing from map.
ORDER_ID のカラムについても、マッピングし同期させるように REPLICAT の設定を変更してみます。
# ggsci 起動
$ /gg/ggsci
# repli2 編集
GGSCI (myora2) x> edit params repli2
# 以下のように編集する
REPLICAT repli2
USERID c##gguser@ORCLPDB1, PASSWORD oracle
MAP ORCLPDB1.c##gguser.ORDER_X, TARGET ORCLPDB1.c##gguser.ORDER_Y COLMAP(ORDER_ID=ORDER_ID, ITEM_ID=ITEM_ID, UNITS=UNITS, CREATED_AT=CREATED_AT, UPDATED_AT=UPDATED_AT, VERSION=VERSION, NUM_SYNC=@COMPUTE(NUM_SYNC + 1));
# Replicat 起動
GGSCI (myora2) x> start repli2
# Oracle PDB ログイン
$ sql c##gguser/oracle@//localhost:1521/ORCLPDB1
SQL> SELECT * FROM ORDER_Y;
ORDER_ID ITEM_ID UNITS CREATED_AT UPDATED_AT VERSION NUM_SYNC
100 200 3 19-SEP-21 19-SEP-21 1 1
ORDER_ID のカラムをマッピングした後は、同期されていることが確認できました。
結果
以上のテスト結果から、以下のことが確認できました。
1.ターゲット側のオートインクリメントのカラムに対して、マッピングの設定をしなければ、自動的に番号が採番されることを期待していたが、出来なかった。
⇒マッピングの設定をしないと、エラーになってしまう。同期処理の時に、オートインクリメントのカラムはターゲット側で自動採番させることは不可能かもしれない。Oracle ドキュメントを探しても、そのような方法は見当たらなかった。
2.同期処理の時に、簡単な計算(今回は+1の加算処理をした上で、ターゲット側のカラムに反映させることには成功した。