Db2での擬似障害からの復旧のまとめ(クラッシュリカバリではなくリストアが必要なケース)。
以下、意図的に破壊行為を働いているので、間違っても大切な環境でのお試しは禁物。。。
前提環境
cat /etc/redhat-release
uname -a
db2licm -l
Red Hat Enterprise Linux Server release 7.3 (Maipo)
Linux db2 3.10.0-514.el7.x86_64 #1 SMP Wed Oct 19 11:24:13 EDT 2016 x86_64 x86_64 x86_64 GNU/Linux
Product name: "IBM DB2 Developer-C Edition"
License type: "Community"
Expiry date: "Permanent"
Product identifier: "db2dec"
Version information: "11.1"
Max amount of memory (GB): "16"
Max number of cores: "4"
Max amount of table space (GB): "100"
テスト対象DB作成
作成するディレクトリは、実環境では全て別ディスクにする想定(マウントポイント)。
循環ログのDB(DB11)
# ディレクトリ作成
mkdir /db/db11
cd /db/db11; pwd
mkdir bkup database tbsp1 tbsp2 log1 log2
# DB作成
db2 "CREATE DB DB11
AUTOMATIC STORAGE YES
ON /db/db11/tbsp1,/db/db11/tbsp2
DBPATH ON /db/db11/database
"
# ログ設定変更
db2 "UPDATE DB CFG FOR DB11 USING
NEWLOGPATH /db/db11/log1
MIRRORLOGPATH /db/db11/log2
"
# 初期データ生成
db2 "CONNECT TO DB11"
db2 "CREATE TABLE Hogetbl (
id INTEGER PRIMARY KEY NOT NULL,
dsc VARCHAR(128))
"
db2 "INSERT INTO Hogetbl VALUES(1, 'hope')"
アーカイブログのDB(DB22)
# ディレクトリ作成
mkdir /db/db22
cd /db/db22; pwd
mkdir bkup database tbsp1 tbsp2 log1 log2 logarch
# DB作成
db2 "CREATE DB DB22
AUTOMATIC STORAGE YES
ON /db/db22/tbsp1,/db/db22/tbsp2
DBPATH ON /db/db22/database
"
# ログ設定変更
db2 "UPDATE DB CFG FOR DB22 USING
NEWLOGPATH /db/db22/log1
MIRRORLOGPATH /db/db22/log2
LOGARCHMETH1 DISK:/db/db22/logarch
"
# 初期バックアップ(アーカイブログ方式に変更したのでBACKUP PENDINGになる)
db2 "BACKUP DB DB22 TO /db/db22/bkup"
# 初期データ生成
db2 "CONNECT TO DB22"
db2 "CREATE TABLE Hogetbl (
id INTEGER PRIMARY KEY NOT NULL,
dsc VARCHAR(128))
"
db2 "INSERT INTO Hogetbl VALUES(1, 'hope')"
Part1. 循環ログでのバックアップとリストア
シナリオ1:テーブルスペースのディスク障害
# バックアップ取得
db2 "FORCE APPLICATIONS ALL"
db2 "TERMINATE"
db2 "DEACTIVATE DB DB11"
db2 "BACKUP DB DB11 TO /db/db11/bkup"
# テーブルスペース擬似障害
rm -rf /db/db11/tbsp[12]/*
# DBアクティベート
db2 "ACTIVATE DB DB11"
SQL0293N Error accessing a table space container. SQLSTATE=57048
# バックアップからリストアして確認
db2 "RESTORE DB DB11 FROM /db/db11/bkup"
db2 "CONNECT TO DB11"
db2 "SELECT * FROM Hogetbl"
ls -l /db/db11/tbsp[12]
シナリオ2:一次トランザクションログのディスク障害
# 一次ログ擬似障害
rm -rf /db/db11/log1
db2 "INSERT INTO Hogetbl VALUES(2,'hoge')" # エラーなし。ミラーログで業務継続
# 復旧
mkdir /db/db11/log1
db2 "FORCE APPLICATIONS ALL"
db2 "TERMINATE"
db2 "DEACTIVATE DB DB11"
db2 "ACTIVATE DB DB11"
ls /db/db11/log1/NODE0000/LOGSTREAM0000
S0000000.LOG S0000002.LOG S0000004.LOG S0000006.LOG S0000008.LOG S0000010.LOG S0000012.LOG
S0000001.LOG S0000003.LOG S0000005.LOG S0000007.LOG S0000009.LOG S0000011.LOG SQLLPATH.TAG
一次ログが復活した。
シナリオ3:トランザクションログのディスク障害(一次、二次とも全滅)
# 擬似障害
rm -rf /db/db11/log[12]
db2 "DELETE FROM Hogetbl" # 戻ってこないしCtrl+cも効かないのでkill -9した
# 再接続を試みる
db2 "CONNECT TO DB DB11"
SQL1034C The database was damaged, so all applications processing the
database were stopped. SQLSTATE=58031
# 完全に壊れた(当たり前)ので落としてログディレクトリ再作成してリストア
# また、コネクションが残っていたりしてDBを正常に非活性にできないので強制終了
db2 "DEACTIVATE DB DB11"
db2stop force # これも効かないのでOS再起動。。。
# ログディレクトリ復旧
mkdir /db/db11/log1 /db/db11/log2
# DBリストアして復旧
db2 "RESTORE DB DB01 FROM /db/db11/bkup"
db2 "ACTIVATE DB DB11"
ls -l /db/db11/log[12]/*/*/*
# 復旧確認
db2 "CONNECT TO DB11"
db2 "SELECT * FROM Hogetbl"
db2 "INSERT INTO Hogetbl VALUES(2, 'hoge')"
db2 "SELECT * FROM Hogetbl"
循環ログではアーカイブログを使ってロールフォワードする必要がない(できない)ので壊れたら戻す、ただそれだけ。
Part2. アーカイブログでのバックアップとリストア
シナリオ1:テーブルスペースとログの障害
# オンラインバックアップ取得
db2 "ACTIVATE DB DB22"
db2 "FORCE APPLICATIONS ALL"
db2 "BACKUP DB DB22 ONLINE TO /db/db22/bkup INCLUDE LOGS"
db2 "LIST HISTORY BACKUP ALL FOR DB22" # ロールフォワードに必要なログがわかる
# テーブルスペース擬似障害
rm -rf /db/db22/tbsp[12]/*
# アーカイブログも喪失
rm -f /db/db22/logarch/dbinst/DB22/NODE0000/LOGSTREAM0000/C000000*/*.LOG
# アクティブログも喪失
rm -f /db/db22/log[12]/*/*/*.LOG
# DBリストア
db2 "DEACTIVATE DB DB22"
# バックアップデータ確認
db2ckbkp -H /db/db22/bkup/DB22.0.dbinst.DBPART000.20181031222046.001
# ログも一緒に戻す
mkdir /db/db22/ovflog
db2 "RESTORE DB DB22 LOGS
FROM /db/db22/bkup TAKEN AT 20181031222046
LOGTARGET /db/db22/ovflog"
# 戻したログからロールフォワード
db2 "ROLLFORWARD DB DB22 TO END OF LOGS OVERFLOW LOG PATH(/db/db22/ovflog)"
# OKならペンディング解除
db2 "ROLLFORWARD DB DB22 COMPLETE OVERFLOW LOG PATH(/db/db22/ovflog)"
# 復旧確認
db2 "ACTIVATE DB DB22"
db2 "CONNECT TO DB22"
db2 "SELECT * FROM Hogetbl"
db2 "INSERT INTO Hogetbl VALUES(2,'hoge')"
db2 "SELECT * FROM Hogetbl"
シナリオ2:テーブルスペースの障害(ログは残存)
# 現行ログ確認
db2 "GET DB CFG FOR DB22" | grep "First active"
# オンラインバックアップ取得(ログ含めず)
db2 "BACKUP DB DB22 ONLINE TO /db/db22/bkup EXCLUDE LOGS"
# バックアップ取得開始時点のアクティブログがアーカイブされている
db2 "GET DB CFG FOR DB22" | grep "First active"
db2 "LIST HISTORY BACKUP ALL FOR DB22" # ロールフォワードに必要なログ確認
オンラインバックアップ取得前のアクティブログ(First active log)は、"S0000004.LOG"だった。
オンラインバックアップ後に当該ログはアーカイブされ、再度確認するとアクティブログは"S0000005.LOG"になった。
当然、LIST HISTORY BACKUP ALL FOR DB22
でレポートされるリストアに必要なログは"S0000004.LOG"となる。
# データ更新
db2 "CONNECT TO DB22"
db2 "INSERT INTO Hogetbl VALUES(3, 'hogehogehoge')"
# テーブルスペース擬似障害
rm -rf /db/db22/tbsp[12]/*
# DBが異常終了したので再起動
db2start
# DBリストア
db2 "DEACTIVATE DB DB22"
db2 "RESTORE DB DB22 FROM /db/db22/bkup TAKEN AT 20181031225356"
db2 "GET DB CFG FOR DB22" | grep "First active" # First active log fileはS0000004.LOGに戻った
db2 "ROLLFORWARD DB DB22 TO END OF LOGS"
db2 "GET DB CFG FOR DB22" | grep "First active" # First active log fileはS0000005.LOGに進んだ
db2 "ROLLFORWARD DB DB22 STOP"
db2 "GET DB CFG FOR DB22" | grep "First active" # First active log fileはS0000006.LOGに進んだ
# 復旧確認
db2 "ACTIVATE DB DB22"
db2 "CONNECT TO DB22"
db2 "SELECT * FROM Hogetbl"
先ほど追加したid=3のデータまで戻った。
オンラインバックアップにログも含めてしまえば(INCLUDE LOGS
でこれがデフォルト動作)、リストア時にログを切り出し(LOGS LOGTARGET ${overflowLogPath}
)、ロールフォワードさせる(OVERFLOW LOG(${overflowLogPath})
)ことができて、とてもシンプルになる。
いずれにせよ、RAID10だったりRAID10でさらにLVMミラーリングしたり(本当にそういうケースがありました)、RAID6あたりだったとしても、おおよそ十分なディスクの冗長化があたりまえな昨今において、いきなりデータディスクが飛ぶなどということは、基幹系のシステムではほとんど考えられないくらいになったものの、致命的に壊れても戻せるという安心感は大切。
蛇足で、少なくとも開発環境でのテストでは、リストア完了後に基本的な操作(SELECT,INSERT,UPDATE)ができることを確認すべき。
以前経験したケースでは、RDBMSの機能を使用して静止化&バックアップしたものをリストアしたら、静止化状態で復旧してきて、それに気がつかなかったということがあったので、、、