HADR構成でのLOAD

通常のLOADはIMPORT（INSERTの繰返し）と違ってログ出力が最低限になるので、ログシッピングを前提としているHADR環境での使用には注意がいる。具体的にはリカバリ（ROLLFORWARD）用のイメージ出力をしつつ、かつそのイメージファイルに**STANDBY側からPRIMARYと同じパスでアクセスできる必要**がある。

+ Db2 v11.1
+ OS: RHEL 7.3
+ DB名: HADRDB
+ PRIMARYホスト: db1
+ STANDBYホスト: db2

# NFS環境
もともと密結合にならざるを得ないHADR環境ではあるが、LOADする場合はさらに密。今回はNASサーバが別にいて各DBサーバからマウントして使用できる、という構成にする。

```text:fstab
nas:/export/disk1  /nfs  nfs  defaults,soft,noauto  0 0
```

このNASサーバはそれほど可用性が高くないので、マウントオプションにsoft,noautoを付与しておく。/nfs/loadディレクトリ下にイメージを出力することにする。PRIMARYとSTANDBY側から同じパスでマウントする。

# 投入データ作成
```bash:PRIMARY
# 投入データ作成
for i in $(seq 1 100000); do
echo "${i},hogehoge${i}" >> hogetbl.csv
done
```

# NONRECOVERABLEなLOADの実験
```bash:PRIMARY
# データ初期化
db2 "TRUNCATE TABLE Hogetbl IMMEDIATE"

# オフラインバックアップ
db2 "TERMINATE"
db2 "DEACTIVATE DB HADRDB"
db2 "BACKUP DB HADRDB TO /nfs"

# LOAD実行
db2 "ACTIVATE DB HADRDB"
db2 "CONNECT TO HADRDB"
db2 "LOAD FROM hogetbl.csv OF DEL INSERT INTO Hogetbl COPY NO"

# HADR確認
db2pd -hadr -db hadrdb # peer
```

```text:db2pd
HADR_FLAGS = STANDBY_TABLESPACE_ERROR SSL_PROTOCOL
```
FLAGSのところにSTANDBY_TABLESPACE_ERRORと出力されている。
また、STANDBYの"_instance_.nfy"ログに以下のようなメッセージが記録される。

```text
ADM5571W  The "DATA" object with ID "4" in table space "2" for table "TBSPACEID=2.TABLEID=4" is being marked as unavailable.
```

STANDBY側に計画切替えして確認する。

```bash:STANDBY
db2 "TAKEOVER HADR ON DB HADRDB"
db2 "CONNECT TO HADRDB"
db2 "SELECT COUNT(*) FROM Hogetbl"
```

```text
SQL1477N  For table "DBINST.HOGETBL" an object "4" in table space "2" cannot 
be accessed.  SQLSTATE=55019
```

出力されたメッセージを元に、わかりきってはいるが対象のテーブルを調べる。

```bash:STANDBY
db2 "SELECT TABNAME FROM SYSCAT.TABLES WHERE TABLEID='4' AND TBSPACEID='2'"
```

HOGETBLが無効になったとわかる。

と、このようにNONRECOVERABLEなLOADをHADR環境で実行すると、STANDBY側でTAKEOVERしても当該表へはアクセスできなくなる。PRIMARYでどのような更新があったとしてもスキップされる。
LOAD元ファイル（今回の例ではhogetbl.csv）がSTANDBY側にも転送されて、TAKEOVER時にDROP TABLE/CREATE TABLE/LOADするという運用になっているならそれはそれでOKではある。とにかく、STANDBY側でこれを復旧するには、一度対象のテーブルをDROPしてCREATEしなおすか、バックアップからリストアする必要がある。
今回は０件状態のバックアップからリストアして復旧。

```bash:PRIMARY/STANDBY
db2 "TERMINATE"
db2 "DEACTIVATE DB HADRDB"
db2 "RESTORE DB HADRDB FROM /nfs"
db2 "START HADR ON DB HADRDB AS ${HADR_ROLE}" # STANDBY|PRIMARYの順
db2pd -hadr -db hadrdb  # peer
```

# COPY YESでのLOADとロールフォワードの実験
```bash:PRIMARY
# バックアップ取得
db2 "BACKUP DB HADRDB ONLINE TO /nfs"

# COPY YESでログ出力しつつLOAD
mkdir /nfs/load
db2 "LOAD FROM /nfs/hogetbl.csv OF DEL INSERT INTO Hogetbl COPY YES TO /nfs/load"

# HADR状態確認
db2pd -hadr -db hadrdb   # peer
# /nfs/loadを確認
ls -l /nfs/load
```

```text
HADRDB.4.dbinst.DBPART000.20181115215259.001  HADRDB.4.dbinst.DBPART000.20181115215326.001
```

ここで障害が発生した想定でバックアップからリストアする。

```bash:PRIMARY
db2 "TERMINATE"
db2 "DEACTIVATE DB HADRDB"
db2 "RESTORE DB HADRDB FROM /nfs TAKEN AT 20181115215120" # さっきとったオンラインバックアップ
db2 "ROLLFORWARD DB HADRDB TO END OF LOGS"                # 戻せるところまでロールフォワード
db2 "ROLLFORWARD DB HADRDB STOP"                          # ペンディング解除
db2 "START HADR ON DB HADRDB AS PRIMARY"                  # HADR復帰
db2pd -hadr -db hadrdb  # peer
db2 "CONNECT TO HADRDB"
db2 "SELECT COUNT(*) FROM Hogetbl"                        # １０万件
```

LOADしたデータもロールフォワードでき、かつHADRもPEERになった（STANDBYでTAKEOVERして更新したりしていない、つまりPRIMARYがROLLFORWARDすることでSTANDBYとデータ整合が取れた）。

では、このログはいつまで必要か、といえば当然次にバックアップを取るまで、ということになる。とはいっても自動で削除してくれるわけではないので、自分で削除する。