PostgreSQL 実践講座 #9 バックアップ・PITR・アップグレード — 障害直前に戻る技術
最終回の主題は、最悪の日のための準備です。基礎第 9 回の pg_dump は良い出発点でしたが、「昨日未明以降のデータはない」という限界がありました。本番 DB の目標はもっと高いところにあります。事故の直前の時点に戻ること。 その技術が PITR で、材料は前回登場した WAL です。
レプリケーションはバックアップではありません #
まず、よくある誤解の整理からです。「スタンバイがあるからバックアップは大丈夫」は間違いです。レプリケーションは障害を防ぎ、バックアップは失敗を巻き戻します。 DELETE FROM users をうっかりコミットすれば、その DELETE はミリ秒後にスタンバイでも忠実に再生されます。フェイルオーバーしたところで、すでに消えた DB がもう 1 つあるだけです。ハードウェア障害の答えがレプリケーションなら、人間のミスとソフトウェアのバグの答えは、時間を巻き戻すバックアップです。両方必要です。
PITR: ベースバックアップ + WAL の再生 #
原理は前回のレプリケーションと正確に同じ材料の、別の使い方です。ストリーミングレプリケーションが WAL をリアルタイムに再生して「現在のコピー」を作るなら、PITR は保管しておいた WAL を望む時刻までだけ再生して「過去のコピー」を作ります。 必要なものは 2 つです。
# 1) 定期的なベースバックアップ(稼働中に取れます。例: 毎日未明)
pg_basebackup -D /backup/base -Ft -z -P
# 2) postgresql.conf: WAL を保管場所へコピーし続ける
archive_mode = on
archive_command = 'cp %p /backup/wal/%f' # 実務では S3 などのリモートストレージへ復旧は「ベースバックアップを展開し、目標時刻を指定して WAL を再生」です。
restore_command = 'cp /backup/wal/%f %p'
recovery_target_time = '2026-08-31 14:29:00+09' # 事故が 14:30 だったならその直前へこの組み合わせがあれば、復旧できる時点は「昨日未明」ではなく WAL が残っている任意の時刻になります。事故の時刻を突き止めること(ログ、pg_stat_statements の痕跡)までが復旧作業の一部です。実務ではこの全体を手で組む代わりに pgBackRest のような専用ツールで管理するのが標準で、マネージドサービスの「特定時点への復元」機能は、まさにこの構造を商品化したものです。そして基礎第 9 回の文はここでも有効です。復元リハーサルのない PITR 構成は、構成ではなく願望です。 定期的に実際の復旧訓練を回す必要があります。
メジャーアップグレード: 3 つの道 #
PostgreSQL は毎年メジャーバージョンが出て、各バージョンは 5 年サポートです。先送りすると一度に何バージョンも跳ぶことになるので、アップグレードは運用カレンダーの定期行事にしておくのが正解です。道は 3 つです。
| 方法 | 停止時間 | 特徴 |
|---|---|---|
| pg_dump → 新バージョンへ復元 | 長い(サイズに比例) | 一番単純、小さい DB 専用 |
| pg_upgrade | 短い(分単位) | その場での変換。--link モードなら大容量でも分単位 |
| 論理レプリケーション | 秒単位 | 新バージョンのサーバーを購読者として立てて切り替え。一番精密で、一番手がかかる |
実務の既定値は pg_upgrade です。データファイルのフォーマットの互換性を利用してカタログだけを変換するので、数百 GB の DB でも分単位の停止で終わります。その停止すら難しいサービスなら、前回の論理レプリケーションで新バージョンのサーバーを並べて立てておき、接続だけ切り替える方法が残っています。どの道でも共通の規律は同じです。ステージングで同じ手順のリハーサルをし、アップグレード直後に ANALYZE を回し(統計は引き継がれません)、拡張(extension)たちの互換バージョンを事前に確認することです。
トラックを終えて #
これで実践 9 回、基礎から 18 回のトラックが終わりました。無停止マイグレーションから出発して、コネクション、診断、インデックス戦略、VACUUM、ロック、パーティショニング、レプリケーション、そして PITR まで。振り返ると、1 つの原理がずっと繰り返されていました。MVCC と WAL という 2 本の柱を理解すれば、運用の問題たちはその帰結として説明できます。 dead tuple も、ロックのルールも、レプリケーションも、PITR もそうです。今度見知らぬ症状にぶつかったら、この 2 本の柱に戻って「バージョンはどう積もり、ログはどこへ流れるのか」を問うてください。このトラックがその問いの地図になれば幸いです。
まとめ #
- レプリケーションは障害用、バックアップは失敗用です。DELETE 事故はスタンバイでも再生されるので、フェイルオーバーでは戻せません。
- PITR = ベースバックアップ(pg_basebackup) + WAL アーカイブ + 目標時刻の再生です。復旧できる時点が「任意の時刻」になります。
- 実務の構成は pgBackRest のようなツールが標準で、マネージドの特定時点復元は同じ構造の商品です。リハーサルは必須です。
- メジャーアップグレードの既定値は pg_upgrade(分単位の停止)で、無停止が必要なら論理レプリケーションでの切り替えです。直後の ANALYZE を忘れないでください。
- トラックの結論は 2 本の柱です。MVCC と WAL を理解すれば、運用の問題たちが原理の帰結として解けていきます。