PostgreSQL復元実験:5件のデータと壊れたバックアップの記録

公開日: 2026-09-14 / 運用・復元 #復元 #PostgreSQL #ローカル検証

復元はコマンドの終了だけで合格にしない。元の内容と照合し、壊れた保存物が失敗として検知されるところまで試す。今回は架空の5件を使い、9項目を確認した。

2026年9月14日のローカル検証記録である。Docker Desktop上のPostgreSQL 18.6(Debian、aarch64)を使った。有料VPSには接続しておらず、実利用者のデータや稼働中のDBは扱っていない。

元のDBを残したまま、空の別DBへ戻した

新規コンテナ内にlab_source、lab_restored、失敗用のlab_badを作成した。ネットワークはnone、ホストへのポート公開はなし。1 CPU・512 MiBの上限を付けたが、この値は小さな実験を隔離するための設定で、運用に推奨するサーバー仕様ではない。

元データは次の5行だけだ。金額欄も試験用の整数であり、実際の取引ではない。

id label amount
1 sample-a 125
2 sample-b 250
3 sample-c 0
4 sample-d 875
5 sample-e 1000

主キー、labelの索引、amountを0以上に限定するCHECK制約、件数と合計を返すビューも用意した。単純な行コピーでは見落とす部分を照合するためだ。

pg_dump -Fcでカスタム形式を出力し、pg_restore --exit-on-error --single-transactionで空の復元先DBに読み込んだ。元DBの削除や上書きはしていない。

PostgreSQLのpg_restore資料では、既定はSQLエラー後も処理を続ける。今回はエラーで止め、全体を一つのトランザクションとして扱うオプションを付けた。巨大なDBにもこの設定が常に適切とは限らないので、対象の規模と版に合う復元計画が別途必要になる。

確かめた9項目

照合 観測した結果
id順のCSV 元と復元先がバイト単位で一致
復元したビュー 5件、amount合計2250
索引 主キーとlabel索引の2本が存在
CHECK制約 amountが負の行の挿入を拒否
壊したアーカイブ 先頭32バイトだけ渡すと終了コード1
失敗先DB publicスキーマに表は作られていなかった
元DB 一連の操作後も同じCSVを返した
ダミー設定ファイル tarから戻した内容が元と一致
ダミー添付ファイル tarから戻した内容が元と一致

壊したアーカイブではend of fileを含むエラーが出た。これはアーカイブ先頭の読み取り段階で失敗させたケースで、途中までSQLを実行した後のロールバックを実証したものではない。

ファイルの検証に使ったのは、試験用settings.jsonとattachment.txtの2点。稼働中のDBディレクトリをtarで固めた実験ではない。DBの整合性と、通常ファイルのコピー一致は分けて確認した。

小さな成功から分かる範囲

この実験では、ダンプが2,362バイト、取得が0.226秒、復元が0.205秒だった。新しいDBを準備する時間や障害を検知する時間は、この二つの処理時間に含まれない。ローカルの極小データなので、実サービスの復旧時間、VPS各社の速度、何GBなら何分という見積りには使えない。

クラスタ共通のロール、テーブルスペース、拡張機能、大規模データ、時点復旧、別ホストへの移行は未検証。n8nやDifyを起動して実業務が戻ることも確認していない。pg_dumpの対象は一つのDBであり、クラスタ全体の情報は別の扱いになる。

同じサンプルを手元で試す

実行スクリプト、今回のJSON記録、元のCSV、復元後のCSVを公開する。

Python 3.12以降とDockerを使い、新しい作業フォルダにスクリプトを保存する。先にdocker pull postgres:18でイメージを用意し、そのフォルダでpython3 run.pyを実行する。記録には実際に使った版とイメージの識別値が残る。タグの取得時期やCPU環境によって今回と同じ版にならない場合がある。

スクリプトは自分で新設した隔離コンテナだけを片付け、CSVやレポートを作業フォルダに残す。認証を省く設定は、ネットワークなし・ポート公開なしの架空データ実験に限定している。本番の接続先や鍵をこの例へ差し込む用途ではない。

自分の復元訓練に足すもの

次は「画面が開く」からもう一段先を確認する。試験環境で添付を開く、ログインする、外部へ送信しないサンプル処理を実行するなど、サービスごとの復旧条件を決める。

保存物の取得日時、許容するデータの欠損、担当者、検知から再開までの時刻、再開を承認した人を記録に残す。秘密情報が不足するなら、サーバーを大きくしても復元は進まない。

資料確認日: 2026年9月14日。実行時刻・全照合結果は上記JSON記録に収録している。