バックアップの話で最も大事なのは、コマンドの細部ではありません。**「いざというとき、本当に戻せるのか」**です。取れているつもりのダンプが壊れていた、復旧手順を誰も知らなかった、戻すのに丸一日かかった——これらは全部、復旧をテストしていないことが原因です。
この記事は、PostgreSQL のバックアップと復旧を「戻せる」前提で設計するためのガイドです。3方式の使い分けから、PITR(任意の時点への復旧)の設定と実際の復旧手順まで、公式ドキュメントに忠実に解説します。本番運用ガイド §2の深掘り——運用で最初に固めるべき領域です。
この記事のルール:バックアップ方式・コマンド・PITR の仕様・PostgreSQL 18/17 の機能は PostgreSQL 18 公式ドキュメント(2026年6月時点) に基づきます。RPO/RTO という用語は運用設計の一般語(公式ドキュメントの語ではない)として使います。マネージド(RDS等)の自動化はベンダー機能として明記します。
1. まず指標で考える:RPO と RTO
方式選定の前に、2つの指標で要件を言語化します。
- RPO(Recovery Point Objective):障害時にどれだけのデータ損失を許容するか。「最大15分」「ゼロ」など。
- RTO(Recovery Time Objective):障害からどれだけ早く復旧する必要があるか。「1時間以内」など。
この2つが方式を決めます。「夜次ダンプだけ」なら RPO は最大24時間(前回ダンプ以降を失う)。「1分も失えない」なら継続的アーカイブやレプリケーションが要ります。要件を数字にしてから方式を選ぶ——これが順番です。
2. 3つのバックアップ方式
PostgreSQL のバックアップは公式に3方式。
| 方式 | 何ができる | 向く場面 | 限界 |
|---|---|---|---|
論理(pg_dump) | 稼働中に一貫スナップショット。SQL/可搬・選択復元・バージョン跨ぎ | 単一DBの移行・部分復元・小〜中規模 | DB単位。ロール/テーブルスペースは含まない |
| 物理(ファイルコピー) | データファイルを丸ごとコピー | 単純な全クラスタ複製 | サーバー停止が必須。クラスタ単位のみ |
| 継続的アーカイブ(WAL) | ベースバックアップ+WAL退避で任意の時点に復旧(PITR) | 本番基幹・低RPO・大規模 | 設定が複雑・クラスタ単位 |
公式は物理ファイルバックアップについて明確に警告します:「使えるバックアップを得るにはデータベースサーバーを停止しなければならない。全接続を禁止する程度の中途半端な対策では機能しない」。だから稼働中の物理バックアップは、後述の pg_basebackup か、ファイルシステムスナップショットを使います。
3. 論理バックアップ:pg_dump / pg_dumpall
pg_dump は最も手軽で可搬性が高い方式。公式曰く「pg_dump のダンプは内部的に一貫しており、pg_dump 開始時点のスナップショットを表す。pg_dump は処理中も他の操作をブロックしない」。稼働中に安全に取れます。
# 1) プレーンSQL(小規模・人間が読める)
pg_dump appdb > appdb.sql
psql -X -d appdb < appdb.sql # 復元
# 2) カスタム形式(推奨:圧縮・選択復元・並列復元が可能。復元は pg_restore)
pg_dump -Fc appdb > appdb.dump
pg_restore -d appdb appdb.dump
# 3) ディレクトリ形式 + 並列ダンプ/復元(大きいDBを速く)
pg_dump -Fd -j 4 -f appdb.dir appdb
pg_restore -d appdb -j 4 appdb.dir
最重要の落とし穴:pg_dump は単一DBしか対象にせず、ロール(ユーザー)・テーブルスペースなどクラスタ全体の定義を含みません。これらは pg_dumpall で別途取ります。
# クラスタ全体(ロール・テーブルスペース込み)
pg_dumpall > cluster.sql
# ロール/テーブルスペースだけ(グローバルのみ)— pg_dump と組み合わせる定番
pg_dumpall --globals-only > globals.sql
「
pg_dumpで完璧」と思っていたら、復元先にロールが無くて権限が全部外れた——よくある事故です。**pg_dumpall -g(globals)+pg_dump -Fc(各DB)**をセットで運用しましょう。
PostgreSQL 18 では pg_dump/pg_restore に --statistics(オプティマイザ統計の移行)、--no-data/--no-schema/--sequence-data などの選択オプションが追加されました。
4. 継続的アーカイブと PITR:任意の時点へ戻す
低RPOの本命が継続的アーカイブです。公式の定義:「この技術はポイント・イン・タイム・リカバリ(PITR)を可能にする。ベースバックアップを取った時点以降の任意の時点にデータベースを復旧できる」。
仕組みは「ベースバックアップ(土台)+WALの継続退避(その後の全変更)」。復旧時は、土台を戻してから WAL を目的の時点まで再生します。
4.1 設定:WALをアーカイブする
# postgresql.conf
wal_level = replica # replica 以上(archive を含む)
archive_mode = on
# 成功時のみ 0 を返し、既存ファイルを上書きしない(安全装置)
archive_command = 'test ! -f /mnt/archive/%f && cp %p /mnt/archive/%f'
公式が強調する2つの鉄則:
- 「アーカイブコマンドは、成功した場合に限り(if and only if)ゼロを返さねばならない」。0を返すと PostgreSQL はそのWALを削除・再利用するため、嘘の成功はWAL消失=復旧不能を招きます。
- 「既存のアーカイブファイルを上書きしないよう設計すべき」。管理者ミスからアーカイブの完全性を守る重要な安全機能です(上の
test ! -fがそれ)。
実運用では
cpではなく、pgBackRestやWAL-G、クラウドストレージ(S3等)への転送に置き換えます。これらは並列・圧縮・暗号化・保持ポリシー・リストア検証まで面倒を見てくれます。
4.2 ベースバックアップ:pg_basebackup
# 稼働中にベースバックアップ(クラスタ全体)。-X stream で自己完結、-R で復旧設定を生成
pg_basebackup -D /backup/base -Ft -z -X stream -c fast -R
# -Ft: tar形式 / -z: 圧縮 / -X stream: WALを並列ストリーム同梱 / -c fast: 即時チェックポイント
# -R: standby.signal と接続設定を書き出す(スタンバイ構築にも流用)
公式:「pg_basebackup は稼働中のクラスタのベースバックアップを取る。他のクライアントに影響を与えずに実行できる」。
4.3 復旧:目的の時点まで再生する
障害時、ベースバックアップを展開し、復旧設定を書いて起動すると、PostgreSQL が WAL を再生して目的の時点まで戻します。
# 復旧先の postgresql.conf(または postgresql.auto.conf)
restore_command = 'cp /mnt/archive/%f %p' # アーカイブからWALを取り出す
recovery_target_time = '2026-06-24 09:41:00+09' # ここまで再生(誤DELETEの直前など)
recovery_target_action = 'promote' # 到達したら通常稼働へ昇格
# データディレクトリに recovery.signal を置くと「目標復旧→昇格」モードで起動する
touch /var/lib/postgresql/18/main/recovery.signal
pg_ctl start
公式の要点:
- 「絶対に指定しなければならないのは
restore_command」——アーカイブからWALを取り出す方法。 - 復旧目標は
recovery_target_time/_lsn/_xid/_nameのいずれか(実用的なのは時刻と名前付き復元ポイント)。 recovery.signalがあれば「目標まで復旧して昇格」、standby.signalならスタンバイとして起動(HA記事)。完了時に信号ファイルは自動削除されます。- 停止点はベースバックアップの終了時刻より後でなければならない(バックアップ取得中の時点へは戻せない)。
backup_labelファイルは「単なる情報ではなく、復旧処理の正しい動作に不可欠」——消さない。
誤操作からの救済:PITR の真価は「誤った
DELETE/DROPの直前に戻せる」こと。recovery_target_timeをインシデント直前に設定すれば、人為ミスを巻き戻せます。これは単純なスナップショットにはできない芸当です。
5. 増分バックアップ(PostgreSQL 17+)
PostgreSQL 17 で増分バックアップが入りました(PG18 の新機能ではない点に注意)。前回バックアップ以降の差分だけを取り、容量と時間を削減します。
# フル → 増分(前回のマニフェストを参照)
pg_basebackup -D /backup/full -X stream
pg_basebackup -D /backup/incr1 --incremental=/backup/full/backup_manifest -X stream
# 増分は単独では使えない。pg_combinebackup でフルと合成してから復元する
pg_combinebackup /backup/full /backup/incr1 -o /backup/restored
公式:「増分バックアップは直接使えない。まず pg_combinebackup で、それが依存する以前のバックアップと合成しなければならない」。PostgreSQL 18 では pg_combinebackup に -k/--link(ハードリンク)、pg_verifybackup のtar形式検証対応などが追加されました。
6. 「戻せる」を保証する:復旧訓練を自動化する
バックアップ戦略の唯一の正しい検証は、実際に復元してみることです。これをCIや定期ジョブに組み込みます。
#!/usr/bin/env bash
# 定期実行する復旧訓練(最新バックアップを隔離環境に戻し、健全性を検証)
set -euo pipefail
RESTORE_DIR=$(mktemp -d)
trap 'rm -rf "$RESTORE_DIR"' EXIT # 後始末(冪等・再実行安全)
# 1) 最新のフル+増分を合成して復元
pg_combinebackup /backup/full /backup/incr-latest -o "$RESTORE_DIR/data"
# 2) 隔離ポートで起動し、復旧完了を待つ
pg_ctl -D "$RESTORE_DIR/data" -o "-p 5499" start
until pg_isready -p 5499; do sleep 1; done
# 3) スモークチェック:行数や重要テーブルの存在を検証(戻ったことの証拠)
psql -p 5499 -d appdb -At -c "SELECT count(*) FROM orders" | grep -Eq '^[0-9]+$'
# 4) 停止(健全なら成功。失敗すれば非0で落ち、アラートが鳴る)
pg_ctl -D "$RESTORE_DIR/data" stop
echo "restore drill OK"
可観測性:この訓練ジョブの成否を監視に載せ、失敗=バックアップが壊れているとして即アラートします。「バックアップが取れているか」ではなく「戻せるか」を毎日確認するのが、本物の信頼性です。
7. マネージドの場合(RDS/Aurora/Cloud SQL)
マネージドサービスは、ここまでの継続的アーカイブとPITRを自動化します(ベンダー機能・公式PostgreSQLドキュメント外)。自動スナップショット+WALの継続退避により、コンソールやAPIから「特定タイムスタンプへの復元」が可能です。archive_command や pg_basebackup を手で運用する必要はありません。
ただし、論理バックアップ(pg_dump)は別途検討する価値があります。マネージドのスナップショットはクラスタ単位の物理復元が中心で、「特定のテーブルだけ別環境に復元」「バージョン跨ぎの移行」「マネージド障害に依存しない外部保管」には論理ダンプが有効です。多層防御として、マネージドPITR+定期 pg_dump の外部保管を組み合わせるのが堅実です。
8. まとめ
- 「戻せる」が正義。RPO/RTO を数字にしてから方式を選び、復旧訓練を自動化する。
- 3方式:論理(
pg_dump、稼働中・可搬・DB単位)/物理(停止必須)/継続的アーカイブ(PITR)。 - 低RPOは継続的アーカイブ。
archive_commandは成功時のみ0・上書き禁止、pg_basebackupでベース、復旧はrestore_command+recovery_target_time+recovery.signal。 pg_dumpはロール/テーブルスペースを含まない——pg_dumpall -gを併用。- 増分バックアップは PG17+(
--incremental+pg_combinebackup)。 - マネージドはPITRを自動化するが、論理ダンプの外部保管で多層防御を。
「壊さない」が固まったら、次は「落ちても止まらない」——ストリーミングレプリケーションと高可用性 へ。