# PostgreSQL バックアップ & PITR 実践（pg_dump / 継続的アーカイブ / WAL / Point-in-Time Recovery・v18対応）

> PostgreSQL のバックアップと復旧を本番品質で設計する実践ガイド。論理(pg_dump)・物理・継続的アーカイブの3方式の使い分け、pg_dump/pg_restoreの実コマンド、WALアーカイブとpg_basebackupによるPITR（任意の時点への復旧）の設定と復旧手順、PostgreSQL 17の増分バックアップ、復旧訓練の重要性、マネージドの自動PITRまでを、公式ドキュメントに忠実に解説します。

- 公開日: 2026-06-24
- 著者: 友田 陽大
- タグ: PostgreSQL, アーキテクチャ設計
- URL: https://tomodahinata.com/blog/postgresql-backup-pitr-pg-dump-wal-archiving-guide

## 要点

- バックアップの正義は『取れている』ではなく『戻せる』。テストしていない復旧手順は存在しないのと同じ。RPO(どれだけ失うか)とRTO(どれだけ早く戻すか)で設計する
- 3方式：論理(pg_dump=稼働中・一貫スナップショット・可搬・DB単位)、物理ファイル(サーバー停止必須)、継続的アーカイブ(WAL=任意の時点に復旧=PITR)
- 夜次のpg_dumpだけだと最大24時間失う(高RPO)。継続的アーカイブ＝ベースバックアップ+WAL継続退避なら、データ損失をほぼゼロにできる
- PITRの肝：archive_commandは成功時のみ0を返し既存ファイルを上書きしない、pg_basebackupでベース取得、復旧はrestore_command+recovery_target_time+recovery.signal+recovery_target_action='promote'
- PostgreSQL 17で増分バックアップ(pg_basebackup --incremental + pg_combinebackup)、PG18でpg_verifybackupのtar対応・pg_dumpの--statistics等が追加。pg_dumpはロール/テーブルスペースを含まない(pg_dumpall -gが必要)

---

バックアップの話で最も大事なのは、コマンドの細部ではありません。**「いざというとき、本当に戻せるのか」**です。取れているつもりのダンプが壊れていた、復旧手順を誰も知らなかった、戻すのに丸一日かかった——これらは全部、**復旧をテストしていない**ことが原因です。

この記事は、PostgreSQL のバックアップと復旧を「戻せる」前提で設計するためのガイドです。3方式の使い分けから、PITR（任意の時点への復旧）の設定と**実際の復旧手順**まで、公式ドキュメントに忠実に解説します。[本番運用ガイド §2](/blog/postgresql-production-operations-guide)の深掘り——運用で最初に固めるべき領域です。

> **この記事のルール**：バックアップ方式・コマンド・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 は処理中も**他の操作をブロックしない**」。稼働中に安全に取れます。

```bash
# 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` で別途取ります。

```bash
# クラスタ全体（ロール・テーブルスペース込み）
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をアーカイブする

```ini
# postgresql.conf
wal_level = replica           # replica 以上（archive を含む）
archive_mode = on
# 成功時のみ 0 を返し、既存ファイルを上書きしない（安全装置）
archive_command = 'test ! -f /mnt/archive/%f && cp %p /mnt/archive/%f'
```

公式が強調する2つの鉄則：

1. **「アーカイブコマンドは、成功した場合に限り（if and only if）ゼロを返さねばならない」**。0を返すと PostgreSQL はそのWALを削除・再利用するため、嘘の成功は**WAL消失**＝復旧不能を招きます。
2. **「既存のアーカイブファイルを上書きしないよう設計すべき」**。管理者ミスからアーカイブの完全性を守る重要な安全機能です（上の `test ! -f` がそれ）。

> 実運用では `cp` ではなく、`pgBackRest` や `WAL-G`、クラウドストレージ（S3等）への転送に置き換えます。これらは並列・圧縮・暗号化・保持ポリシー・**リストア検証**まで面倒を見てくれます。

### 4.2 ベースバックアップ：pg_basebackup

```bash
# 稼働中にベースバックアップ（クラスタ全体）。-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 を再生して目的の時点まで戻します。

```ini
# 復旧先の 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'              # 到達したら通常稼働へ昇格
```

```bash
# データディレクトリに 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記事](/blog/postgresql-streaming-replication-high-availability-failover-guide)）。完了時に信号ファイルは自動削除されます。
- **停止点はベースバックアップの終了時刻より後**でなければならない（バックアップ取得中の時点へは戻せない）。
- `backup_label` ファイルは「単なる情報ではなく、復旧処理の正しい動作に**不可欠**」——消さない。

> **誤操作からの救済**：PITR の真価は「**誤った `DELETE`/`DROP` の直前**に戻せる」こと。`recovery_target_time` をインシデント直前に設定すれば、人為ミスを巻き戻せます。これは単純なスナップショットにはできない芸当です。

---

## 5. 増分バックアップ（PostgreSQL 17+）

PostgreSQL **17** で**増分バックアップ**が入りました（PG18 の新機能ではない点に注意）。前回バックアップ以降の差分だけを取り、容量と時間を削減します。

```bash
# フル → 増分（前回のマニフェストを参照）
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や定期ジョブに組み込みます。

```bash
#!/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を自動化**するが、論理ダンプの外部保管で多層防御を。

「壊さない」が固まったら、次は「**落ちても止まらない**」——[ストリーミングレプリケーションと高可用性](/blog/postgresql-streaming-replication-high-availability-failover-guide) へ。

---

### 参考（PostgreSQL 18 公式ドキュメント）

- [25.1. SQL Dump](https://www.postgresql.org/docs/18/backup-dump.html)
- [25.3. Continuous Archiving and Point-in-Time Recovery (PITR)](https://www.postgresql.org/docs/18/continuous-archiving.html)
- [pg_basebackup](https://www.postgresql.org/docs/18/app-pgbasebackup.html)
- [pg_combinebackup](https://www.postgresql.org/docs/18/app-pgcombinebackup.html)
- [25. Backup and Restore（概要）](https://www.postgresql.org/docs/18/backup.html)
