Amazon RDS for Db2とのQレプリケーション

# Amazon RDS for Db2とのQレプリケーション
2023年11月より、Db2もAWSのマネージド・サービスとして提供開始されています。


このRDS for Db2とのQレプリケーションのセットアップに関する文書が出たため、それに沿って実際にレプリケーションを動かしてみました。

- [QRep Setup Between Db2 On-Prem and AWS RDS for Db2](https://community.ibm.com/community/user/dataops/viewdocument/qrep-setup-between-db2-on-prem-and?CommunityKey=3bfc9f2f-4a5e-470a-9295-4b7cc90c9518&tab=librarydocuments) <br>

この中では以下の５パターンが示されていますが、今回は2.のパターンを行いました。
1. ソース：RDS for Db2、ターゲット：Db2 LUWオンプレ
2. ソース：Db2 LUWオンプレ、ターゲット：RDS for Db2
3. ソース：RDS for Db2、ターゲット：Db2 for z/OS
4. ソース：Db2 for z/OS、ターゲット：RDS for Db2
5. ソース：RDS for Db2、ターゲット：RDS for Db2
<br>


- 補足）Qレプリケーションとは

「Qレプリケーション」とは、IBM Data Replication(ソフトウェア製品の名称) で提供される、データの送受信にMQメッセージ・キューを利用する、Db2 LUW(Linux,Unix,Windows)環境だけでなくz/OSでも同じアーキテクチャーで動くレプリケーション製品です。

Qレプリケーションには次の３つのコンポーネントがあります。
Qキャプチャー：変更トランザクションの収集
IBM MQ：変更トランザクションの転送
Qアプライ：変更トランザクションをターゲットに適用
<br>
Qレプリケーションそのものの概要は、こちらの資料をご覧ください。
[IBM Support :【SIL】【IM】Qレプリケーション概要](https://www.ibm.com/support/pages/node/6607083)

また、セットアップ手順の解説には、こちらのQiitaも参考にしてください。
[Qレプリケーション・チュートリアル ASNCLP版](https://qiita.com/Seven_Marine/items/a2e93561e6b8629725ee)


# ソース：Db2 LUWオンプレから、ターゲット：RDS for Db2へのレプリケーションの設定

今回行ったのは次のパターンです。
- ソース：Db2 LUWオンプレ、ターゲット：RDS for Db2
![Db2 to RDS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272878/5110d4cf-9181-df29-00dd-c71769a5fd8d.png)



- 使用したソース環境：RHEL 9、Db2 11.5(Linux版)

[QRep Setup Between Db2 On-Prem and AWS RDS for Db2](https://community.ibm.com/community/user/dataops/viewdocument/qrep-setup-between-db2-on-prem-and?CommunityKey=3bfc9f2f-4a5e-470a-9295-4b7cc90c9518&tab=librarydocuments)の、P9〜P14の手順に沿って実施しました。
以下の1.からの番号も、英語文書中の番号と一致しています。

##### 1.ターゲットとなるRDS for Db2インスタンスの情報をメモします。
環境に合わせた値としてください。
ホスト名：　xxx.xxx.xxxxx.xxx.amazonaws.com
ポート　：50000
ユーザー名：admin
パスワード：PASSW0RD
データベース名：RDSTEST1


##### 2.ソースにレプリケーション・ソフトがインストールされていない場合：
a. Db2のインストール
参考になるQiita：[【備忘録】Db2 インストール手順まとめ（Linux）](https://qiita.com/Haruka-Ogawa/items/9576399209b32f3016ea)

補足）QレプリケーションのQキャプチャ/Qアプライといったコンポーネントは、Db2のインストールに含まれます。ただし、IBM Data Replication製品のライセンス・ファイルが別途必要です。

b. MQのインストール
参考になるQiita：[IBM MQのインストール～お役立ちコマンド/メモ](https://qiita.com/motuneko253/items/5ff42f7a69aa6dde6089)
補足）Qレプリケーション用に使う場合は、MQはIBM Data Replication製品のライセンスの中に含まれます。

##### 3.Db2/Linuxオンプレ側で、RDSインスタンス、データベース、およびRDSADMINデータベースをカタログします。
```
$ db2 CATALOG TCPIP NODE QREPL1 REMOTE xxx.xxx.xxx.xxx.amazonaws.com SERVER 50000
$ db2 CATALOG DB RDSTEST1 AS RDSTEST1 AT NODE QREPL1 authentication server_encrypt
$ db2 CATALOG DB RDSADMIN AS RDSADMIN AT NODE QREPL1  authentication server_encrypt
```
##### 4.DBAMD権限で使用するレプリケーション用のIDをRDSインスタンス上に作成します。
今回は簡易的にdb2inst1で作成しました。
```
$ db2 CONNECT TO RDSADMIN USER admin USING PASSW0RD
$ db2 “CALL rdsadmin.add_user(‘db2inst1’, ‘PASSW0RD’)”
$ db2 "CALL rdsadmin.dbadm_grant(?,'RDSTEST1', 'DBADM', 'USER db2inst1')"
```
##### 5.RDSサーバーへの接続をテストします。
```
 $ db2 connect to rdstest1 user admin using PASSW0RD

   Database Connection Information

 Database server        = DB2/LINUXX8664 11.5.9.0
 SQL authorization ID   = ADMIN
 Local database alias   = RDSTEST1
```
##### 6.オンプレミスのDb2/Linuxにレプリケーション用のデータベースを作成します。
今回はDb2にサンプルとして付属のSAMPLEデータベースを作りました。
```
$ db2sampl -sql

  Creating database "SAMPLE"...

  Connecting to database "SAMPLE"...

  Creating tables and data in schema "DB2INST1"...

  'db2sampl' processing complete.
```

DBAMD権限で使用するレプリケーション用のIDを作成します。今回は簡易的にインスタンス・オーナーであるdb2inst1をレプリケーション用にも使います。

##### 7.レプリケーションのソースとしてSAMPLEを構成します。
```
$ db2 "update db cfg for SAMPLE using LOG_APPL_INFO YES IMMEDIATE"; 
$ db2 "update db cfg for SAMPLE using LOG_DDL_STMTS YES IMMEDIATE"; 
$ db2 "update db cfg for SAMPLE using LOGARCHMETH1 LOGRETAIN";
$ db2 "backup db SAMPLE to /tmp"
```

##### 8.レプリケーション・プログラムとasnclpで使用するパスワードファイルを作成します。
```
$ mkdir ~/replication
$ cd ~/replication
$ asnpwd init encrypt password
$ asnpwd add alias RDSTEST1 ID db2inst1 password "PASSW0RD" using "asnpwd.aut";
$ asnpwd add alias SAMPLE ID db2inst1 password "PASSW0RD" using "asnpwd.aut";  
$ asnpwd list

Alias: RDSTEST1  ID: db2inst1

Alias: SAMPLE  ID: db2inst1

Number of Entries: 2
```


##### 9.レプリケーション用のIBM MQキュー・マネージャーを作成します。
```
$ crtmqm DB2_2_RDS_QM
$ strmqm DB2_2_RDS_QM
$ dspmq

QMNAME(DB2_2_RDS_QM)                                      STATUS(Running)
```

##### 10.レプリケーションに必要なIBM MQキューを作成します。
以下の`mq_q.txt`テキストファイルを作成し、`runmqsc DB2_2_RDS_QM < mq_q.txt`で実行します。
```
*
* mq_q.txt Create the queues Restartq, adminq, sendq-recvq (DATAQ), Spill Model queue 
*
*Restart queue
DEFINE QLOCAL('DB2.RESTARTQ') DEFPSIST(YES)
*Administration queue
DEFINE QLOCAL('DB2.ADMINQ') DEFPSIST(YES)
*SendReceive queue
DEFINE QLOCAL('DB2.DATAQ') MAXDEPTH(500000) DEFPSIST(YES)
*Spill queue
DEFINE QMODEL('IBMQREP.SPILL.MODELQ') DEFSOPT(SHARED) MAXDEPTH(500000) MSGDLVSQ(FIFO)
ALTER QMODEL('IBMQREP.SPILL.MODELQ') DEFTYPE(PERMDYN)
*Exit
END
```
```
$ runmqsc DB2_2_RDS_QM < mq_q.txt
```
##### 11.レプリケーション・コントロール・テーブルを作成します。
以下のasnclpスクリプト`qreptablesdb2.clp`を作成し、`asnclp -f qreptablesdb2.clp`で実行します。
```
#
# qreptablesdb2.clp Create Replication control tables 
#
ASNCLP SESSION SET TO Q REPLICATION;
#SET RUN SCRIPT LATER;
SET RUN SCRIPT NOW STOP ON SQL ERROR ON;
SET PWDFILE "asnpwd.aut";
SET SERVER CAPTURE TO DBALIAS SAMPLE;
SET SERVER TARGET TO DBALIAS RDSTEST1;
SET CAPTURE SCHEMA SOURCE QASN;
SET APPLY SCHEMA QASN;
SET QMANAGER "DB2_2_RDS_QM" FOR CAPTURE SCHEMA;
SET QMANAGER "DB2_2_RDS_QM" FOR APPLY SCHEMA;

#DROP CONTROL TABLES ON CAPTURE SERVER; 
#DROP CONTROL TABLES ON APPLY SERVER;

# Create Capture control tables
CREATE CONTROL TABLES FOR CAPTURE SERVER USING RESTARTQ "DB2.RESTARTQ" ADMINQ "DB2.ADMINQ";
# Create Apply control tables
CREATE CONTROL TABLES FOR APPLY SERVER IN UW TBSPACE USERSPACE1;
QUIT;
```
```
$ asnclp -f qreptablesdb2.clp
```


##### 12.ソースであるSAMPLEデータベース内に、レプリケーション(複製)元のテーブルとして、テスト用にテーブルTESTREPL.T1を作成します。
```
$ db2 connect to SAMPLE
$ db2 "CREATE TABLE TESTREPL.T1(C1 INT NOT NULL PRIMARY KEY ENFORCED, C2 CHAR(20)) ORGANIZE BY ROW"
$ db2 "INSERT INTO TESTREPL.T1 VALUES(1, 'Hello World')"
$ db2 connect reset
```


##### 13.レプリケーション・キュー・マップを作成します。
以下のasnclpスクリプト`createqmapdb2.clp`を作成し、`asnclp -f createqmapdb2.clp`で実行します。
```
#
# createqmapdb2.clp Create Replication QMAP 
#
ASNCLP SESSION SET TO Q REPLICATION;
#SET RUN SCRIPT LATER;
SET RUN SCRIPT NOW STOP ON SQL ERROR ON; 
SET PWDFILE "asnpwd.aut";
SET SERVER CAPTURE TO DBALIAS SAMPLE;
SET SERVER TARGET TO DBALIAS RDSTEST1;
SET CAPTURE SCHEMA SOURCE QASN;
SET APPLY SCHEMA QASN;
CREATE REPLQMAP DB2_QASN_TO_RDS_QASN USING ADMINQ "DB2.ADMINQ" RECVQ "DB2.DATAQ" SENDQ "DB2.DATAQ"
NUM APPLY AGENTS 16;
QUIT;
```

```
asnclp -f createqmapdb2.clp
```

##### 14.SAMPLEデータベース内のテーブルTESTREPL.T1を、RDSTEST1データベースのTESTREPL.T1にレプリケーションするQサブスクリプションを作成します。
以下のasnclpスクリプト`createqsubdb2.clp`を作成し、`asnclp -f createqsubdb2.clp`で実行します。
```
#
# createqsubdb2.clp Create Q Subscription 
#
ASNCLP SESSION SET TO Q REPLICATION;
#SET RUN SCRIPT LATER;
SET RUN SCRIPT NOW STOP ON SQL ERROR ON;
SET PWDFILE "asnpwd.aut";
SET SERVER CAPTURE TO DBALIAS SAMPLE;
SET SERVER TARGET TO DBALIAS RDSTEST1;
SET CAPTURE SCHEMA SOURCE QASN;
SET APPLY SCHEMA QASN;

CREATE QSUB SUBTYPE U 
USING REPLQMAP DB2_QASN_TO_RDS_QASN 
(
SUBNAME SUB_TESTREPL_T1 
TESTREPL.T1 
OPTIONS 
HAS LOAD PHASE I 
START AUTOMATICALLY YES 
CREATE IF NOT EXIST 
TARGET NAME TESTREPL.T1 CONFLICT 
RULE K CONFLICT ACTION I ERROR ACTION S 
LOAD TYPE 3
);
QUIT; 
```

HAS LOAD PHASE of ‘I’ は、db2ユーティリティーのLOADを使用した初期ロードが行われることを意味します。

LOAD TYPE 3は、EXPORT/LOADが行われ、RDS for Db2でnon-recoverable loadが行われます。

:::note warn
よって、LOAD後には手動でRDSスナップショットを取得するか、LOADジョブの最後にRDSの自動バックアップを設定する運用を行なってください。
:::


他にロード・オプションとして、LOAD TYPE 2 (EXPORT-IMPORT)も選択可能です。

`asnclp -f createqsubdb2.clp`で実行します。
```
$ asnclp -f createqsubdb2.clp
```
##### 15.逆方向のレプリケーションを設定する場合は、Qアプライを実行するユーザー名をIBMQREP_IGNTRANテーブルに挿入します（今回は省略しました）。
キャプチャーがQアプライプログラムによって適用されたトランザクションのログ・レコードをみても、それをソースに送り返すことはありません。

##### 16.キャプチャーとアプライプログラムを開始します。
```
$ nohup asnqcap capture_server=SAMPLE capture_schema=QASN startmode=COLD logstdout=Y > capture.out & 

$ nohup asnqapp apply_server=RDSTEST1 apply_schema=QASN logstdout=Y > apply.out & 
```
Qキャプチャーはcapture_pathで、Qアプライはapply_pathでパスワードファイルを探します。デフォルトは起動ディレクトリーです。

Qサブスクリプションは START AUTOMATICALLY YESで作成されているため、キャプチャー・プログラムの起動時に自動的に開始されます。

##### 17.ターゲットのRDSTEST1データベースに接続し、サブスクリプションがアクティブであることを確認します。
```
$ db2 "SELECT SUBSTR(SUBNAME,1,25) AS SUBNAME, STATE FROM QASN.IBMQREP_TARGETS WITH UR"
```
テーブルが初期ロードされて、レプリケーションされていることを確認します。
```
$ db2 "select * from testrepl.t1"
```


##### 18.ソースのデータベースに接続し、追加の行を挿入します。
```
$ db2 connect to SAMPLE
$ db2 "INSERT INTO TESTREPL.T1 VALUES(2, '2')"
$ db2 "INSERT INTO TESTREPL.T1 VALUES(3, '3')"
$ db2 "INSERT INTO TESTREPL.T1 VALUES(4, '4')"
$ db2 "INSERT INTO TESTREPL.T1 VALUES(5, '5')"
```

##### 19.ターゲットのRDSTEST1データベースに接続し、差分のレプリケーションがされ、４行がinsertされていることを確認します。
```
$ db2 connect to RDSTEST1 user admin using PASSW0RD
$ db2 "select * from testrepl.t1"
```
これでレプリケーションが確認できました！

# RDS for Db2参考情報

以下の各connpassサイトの下部に、RDS for Db2に関する一連の資料と録画が添付されています。

#### 『RDS for Db2 はじめの一歩』
1.『[RDS for Db2 はじめの一歩・作り方編](https://ibm-developer.connpass.com/event/321924/)』
2.『[RDS for Db2 はじめの一歩・HA(高可用性)編](https://ibm-developer.connpass.com/event/324080/)』
3.『[RDS for Db2 はじめの一歩・バックアップ編](https://ibm-developer.connpass.com/event/324081/)』

#### 『RDS for Db2 データ移行編』
1.  [Part1: S3からロードしてみよう](https://ibm-developer.connpass.com/event/331359/)
2.  [Part2: S3経由のバックアップ/リストアでデータ移行](https://ibm-developer.connpass.com/event/332754/)

3. [Part3: Qレプリケーションでデータ連携](https://ibm-developer.connpass.com/event/334546/)　※このconnpassサイトの「資料」のセッション動画で、当Qiita内容の実演をしていますので、ご覧ください。


# Data Replicationマニュアル
- https://www.ibm.com/docs/ja/idr/11.4.0


#  Db2マニュアル
 - https://www.ibm.com/docs/ja/db2/11.5