データベース

PostgreSQLのバックアップ設計|pg_dumpとPITRの使い分け・復旧検証の手順

PostgreSQLのバックアップ設計|pg_dumpとPITRの使い分け・復旧検証の手順

毎晩pg_dumpを回しているのに、いざ障害が起きると「どこまで戻せるのか」が誰にも答えられない。ダンプファイルは残っているが復元を試したことがない。この二つは別々の失敗に見えて、原因は同じところにあります。取得方法だけを決めて、復旧目標と検証手順を決めていないからです。

この記事は、PostgreSQLのバックアップを取得コマンドの羅列ではなく、復旧できる状態を作る設計として扱う解説です。論理バックアップの形式選択、WALアーカイブによる任意時点への復旧、17系以降の増分バックアップ、そして目標値から方式を決める判断基準までを実行できるコマンド付きで並べます。フル・差分・増分といった方式そのものの一般的な整理はシステムバックアップとは?種類(フル・差分・増分)と方式の選び方に譲り、ここはPostgreSQL固有の実装だけを扱います。データベース全般の位置づけはデータベースとは?種類・DBMS・RDBとNoSQLの選び方を参照してください。数値の前提は18系(2026年8月時点で18.6が最新マイナー)としました。

まとめ:バックアップ方式を決める前に固める5点

結論を5点で先に置きます。第一に、pg_dumpは論理バックアップで、取得した瞬間の一貫した断面しか残りません。任意の時点へ戻す要求があるなら、pg_dumpをいくら細かく回しても要件を満たせないので、最初にここで分岐します。

第二に、pg_dumpallは18でも平文SQLしか出力しません。形式を選ぶ指定そのものが存在せず、復元はpsqlに限られます。クラスタ全体を圧縮形式で一括保存する方法はないため、ロールとテーブルスペースだけをpg_dumpallで抜き、データベース本体は個別にpg_dumpで取る二段構えが実務的な解になります。

第三に、任意時点への復旧はpg_basebackupで取ったベースバックアップと、継続的に退避したWALの両方が揃って初めて成立します。片方だけでは戻せません。設定はwal_level、archive_mode、archive_command、そして復旧側のrestore_commandの4点が骨格です。

第四に、17系以降の増分バックアップはsummarize_walを有効にする必要があり、既定は無効で反映にはサーバの再起動が要ります。しかも取得した増分は単体では起動できず、pg_combinebackupで元のバックアップと合成する工程を挟みます。

第五に、18でpg_dumpに統計情報を含める指定が加わりました。既定では含まれないままなので、リストア直後に実行計画が崩れる定番の事故を避けたいなら明示的に指定します。以下、順に根拠を見ていきます。

pg_dumpとpg_dumpallの形式選択と復元コマンドの対応

論理バックアップはSQL文やアーカイブとしてデータを書き出す方式です。公式文書はpg_dumpについて、同時利用中でも一貫した出力を作り、読み手にも書き手にもロックをかけないと明記しています。稼働中に取れることが前提の道具だと理解しておいてください。

plain・custom・directory・tarの4形式と使い分けの基準

pg_dumpの出力形式は4種類あり、選んだ形式で復元コマンドが変わります。平文だけがpsqlで戻す形式で、残りはpg_restoreを通します。

形式 指定 復元 向く場面
平文SQL -Fp psql 差分確認・小規模
カスタム -Fc pg_restore 既定の選択肢
ディレクトリ -Fd pg_restore 並列取得が要る場合
tar -Ft pg_restore 圧縮不可・順序固定

迷ったらカスタム形式を選んでください。既定で圧縮がかかり、復元時に対象を選んだり順序を組み替えたりできます。並列で取りたい場合だけディレクトリ形式にします。並列取得の指定が使えるのはディレクトリ形式だけで、他の形式に付けても働きません。

pg_dump -Fc -Z 6 -f appdb.dump appdb
pg_dump -Fd -j 4 -f appdb_dir appdb
pg_restore -d appdb_new -j 4 appdb.dump

並列指定は接続数を消費します。指定した数に1を足した本数の接続が開くため、max_connectionsに余裕がない本番環境でそのまま流すと、アプリ側の接続が弾かれます。夜間帯であっても接続上限は先に確認しておきましょう。

pg_dumpallが平文SQLしか出せない前提での二段構え

クラスタ全体を対象にするpg_dumpallには、形式を指定するオプションがありません。18の文書でも出力はpsqlへの入力として使うSQLスクリプトと説明されており、pg_restoreは受け付けません。数百ギガのクラスタを平文一本で扱うのは現実的ではないため、役割を分けます。

pg_dumpall -g > globals.sql
pg_dump -Fc -f appdb.dump appdb
pg_dump -Fc -f logdb.dump logdb

グローバルオブジェクトの指定はロールとテーブルスペースだけを抜き、データベースの中身は含みません。テーブルスペースが不要ならロールのみに絞る指定もあります。ここで抜けるのはPostgreSQLのロールと権限設計|CREATE ROLEの属性とGRANT・既定権限の決め方で扱った属性や所属関係で、復元時はこのSQLを先に流してからデータベース本体を戻す順序になります。

18で増えた統計情報のダンプ指定とリストア直後の性能低下対策

移行やリストアの直後だけクエリが極端に遅い、という現象の多くは統計情報が空だからです。18ではpg_dumpに統計情報を含める指定が加わりました。ただし既定は含めない側で、文書にも既定はダンプしない旨が明記されています。

pg_dump -Fc --statistics -f appdb.dump appdb
pg_dump --statistics-only -f stats.sql appdb

統計だけを別途書き出す指定もあるため、データ移送は従来どおり行い、統計はあとから流し込む運用も組めます。18ではこのほかに、スキーマだけ・データだけを外す指定や、行レベルセキュリティのポリシーを外す指定も追加されました。検証環境へ本番の構造だけを持っていく作業が、オプション1つで済むようになっています。統計を持ち込まない場合は、復元後にANALYZEを流してから利用者を戻してください。統計の劣化そのものへの対処はPostgreSQLのVACUUM運用|autovacuumのしきい値設計とXID周回・肥大の切り分けで扱っています。

pg_basebackupとWALアーカイブでPITRを組む手順

任意の時点へ戻す仕組みは、クラスタ全体の物理コピーと、その後の更新履歴であるWALの組み合わせで作ります。論理バックアップとは別系統の道具立てで、片方の代わりにはなりません。

継続アーカイブを有効にする4つの設定とアーカイブ先の置き場所

まず送り出し側を設定します。wal_levelはreplica以上、archive_modeはon、そして退避方法をarchive_commandかarchive_libraryのどちらかで指定します。前者はシェルコマンド、後者はC言語で書かれたモジュールを呼ぶ方式です。

wal_level = replica
archive_mode = on
archive_command = 'test ! -f /mnt/backup/wal/%f && cp %p /mnt/backup/wal/%f'
archive_timeout = 300

コマンド内の記号は仕様に沿って置き換え可能です。パス全体が入る指定と、ファイル名だけが入る指定の2つがあり、公式の例でも同名ファイルの上書きを防ぐ検査を先に置いています。ここを省くと、タイムライン分岐後に同じ名前のWALが来たとき前の内容を壊します。

更新の少ないシステムでは、WALが埋まるまで退避が起きません。時間指定を入れておけば、その間隔で強制的に切り替わるため、目標復旧時点の粒度を時間で保証できます。退避先は本体と同じディスクに置かないでください。同じ筐体が壊れたときに両方失う構成では、そもそも目的を果たしません。退避先の保護についてはPostgreSQLの暗号化|TLS設定・pgcryptoの列暗号化とTDE不在時の選び方を参照してください。

復旧時に置くsignalファイルとrecovery_targetの指定

ベースバックアップの取得はpg_basebackupで行います。WALの同時取り込みを指定すれば、アーカイブを参照しなくても単体で起動できる状態になります。

pg_basebackup -D /mnt/backup/base_20260826 -Ft -z -Xs -P

WALの取り込み方法は3種類です。既定はストリーム方式で、バックアップと並行して別接続でWALを受け取ります。取得完了後にまとめて受け取る方式もありますが、その間にWALが再利用されると失敗するため、保持量の設定を上げておく必要があります。

復旧するときは、ベースバックアップを展開したうえで復旧用の設定を書き、データディレクトリに合図となるファイルを置きます。読み取り専用の待機系として起動する場合は別のファイル名になるので、取り違えないでください。

restore_command = 'cp /mnt/backup/wal/%f %p'
recovery_target_time = '2026-08-26 09:15:00+09'
recovery_target_action = 'promote'

停止位置は時刻のほかに、名前付きの復旧地点、トランザクションID、ログの位置でも指定できます。誤ってテーブルを消した事故なら、その直前の時刻を指定するのが定石です。復旧を始めるにはデータディレクトリにrecovery.signalを作成します。待機系として起動するときはstandby.signalを使います。

17系以降の増分バックアップとpg_combinebackupの必須手順

17系からpg_basebackupに増分の指定が入りました。前回のバックアップに付いてきたマニフェストファイルを渡すと、差分だけを受け取れます。ただし前提が2つあります。

ひとつはサーバ側の設定です。WALの要約処理を担うプロセスは既定で止まっており、summarize_walを有効にしてサーバを再起動しないと増分取得そのものが成立しません。wal_levelがminimalのままでは起動できない制約も付きます。もうひとつはサーバのバージョンで、増分の指定は17以降にしか効きません。

pg_basebackup -D /mnt/backup/full -Xs
pg_basebackup -D /mnt/backup/incr1 -Xs -i /mnt/backup/full/backup_manifest
pg_combinebackup /mnt/backup/full /mnt/backup/incr1 -o /var/lib/pgsql/18/data

増分バックアップは単体では使えません。公式文書も、pg_combinebackupで依存元のバックアップと合成してからでないと使えないと明記しています。ここを知らずに増分だけを遠隔地へ送っている構成は、災害時に何も戻せない状態です。合成の入力には連鎖する全世代が要るため、途中の1世代が欠けた時点でその後の増分はすべて無価値になります。世代数を増やすほど合成時間も伸びるので、週次でフルを取り直す設計が扱いやすいでしょう。

RPOとRTOの目標値からバックアップ方式を決める実務の判断基準

方式選定は好みではなく、許容できるデータ損失量と復旧までの時間で決まります。この2つの指標そのものの定義はリカバリーとは?意味・リストア/バックアップとの違いと企業の実務判断で扱っているので、ここでは数値から方式へ落とす部分だけを書きます。

論理バックアップだけで足りる場面と物理構成が要る場面の線引き

判断は単純です。損失許容が1日単位なら夜間のpg_dumpで足ります。1時間を切る要求が出た瞬間に、WALアーカイブが必須になります。

損失許容 復旧時間 採る方式
1日 数時間可 夜間pg_dump
数時間 1時間以内 基本+WAL退避
5分以内 10分以内 退避+待機系
ほぼ0 数分 同期レプリカ併用

表の下2段はバックアップの話を超えて可用性設計の領域に入ります。待機系を持つ構成でも、論理バックアップは別途必要です。誤ったUPDATEはレプリカにも伝わるため、人的ミスからの復旧手段としては物理複製が役に立ちません。この点を混同した設計を実際によく見かけます。

RPOを分単位まで詰めるときに追加で必要になる設定と運用費用

分単位を狙うなら、WALの強制切り替え間隔を短くし、退避先を別拠点に置きます。退避が滞ったときの検知も要ります。アーカイブが失敗し続けると、サーバはWALを削除できず領域を食い潰してやがて停止するからです。監視対象に退避の成否と滞留数を必ず入れてください。

費用の面では、退避先の容量が更新量に比例して増加する構造です。更新の多い業務システムでは、日次のフルバックアップ容量よりWALの総量が上回る場面もあります。保持期間を決めずに始めると、半年後に保管費用の話が持ち上がります。世代の削除規則を最初に決めておきましょう。

マネージドサービスへ寄せたときに残る自前の作業と責任の分界点

クラウドのマネージドサービスを使うなら、退避の仕組み自体は用意されています。Amazon RDS for PostgreSQLとは?マルチAZ構成・拡張機能の統制と延長サポート課金・DMS移行を実装目線で解説で扱った自動バックアップや、Aurora PostgreSQLとは?対応バージョン・拡張機能とBabelfish・RDSからの移行判断を実装者目線で解説の継続的な保護がそれにあたります。

ただし残る作業があります。保持期間の設定、リージョンをまたぐ複製の有無、そして論理バックアップの取得です。マネージド側の仕組みは同一アカウント内の障害には強い一方、アカウント自体を失う事故や、他クラウドへ持ち出す要求には応えられません。四半期に一度は自分の手元にpg_dumpを落としておく運用を勧めます。

リストア手順を定期検証して復旧できる状態を保つ運用の組み立て方

バックアップは取得した時点では何も保証していません。戻せることを確かめて初めて資産になります。ここを運用に組み込めているかどうかが、事故のときの差になります。

復旧訓練で必ず測る3つの数字とバックアップ台帳に残す確認項目

訓練で測るのは3つです。ひとつめは展開から起動までにかかった実時間で、これが目標復旧時間に収まっているかが確認対象です。ふたつめは復旧できた最終更新時刻で、目標との差が実際の損失量になります。みっつめは復旧後の件数照合で、主要テーブルの行数とチェックサムを取得時と突き合わせます。

記録に残す項目は、実施日、対象世代、所要時間、戻せた時点、照合結果、詰まった箇所の6つで足ります。詰まった箇所の記録がいちばん価値を持ちます。二回目の訓練で同じ場所に引っかかるなら、手順書ではなく構成のほうに問題があると判断してください。

バージョン互換で詰まる場面とpg_restoreの実行順序の注意

復旧時に慌てて気づくのがバージョンの向きです。pg_dumpは自分より古いサーバからは取得でき、出力は自分より新しいサーバへ読み込める前提で作られています。逆向きは通りません。自分より新しいメジャーバージョンのサーバからは、無効なダンプを作る危険を避けるため取得を拒否します。移行作業では新しい側のpg_dumpを使うのが原則です。

物理バックアップはさらに厳格で、メジャーバージョンをまたいだ復元ができません。18のデータディレクトリを17のサーバで起動することも、その逆もできない仕組みです。手元の作業機に入れたクライアントの版が古いまま作業して失敗する例が多いので、PostgreSQLのインストール手順|Windows・Ubuntu別の導入とinitdbで決まる文字コードの手順で版を揃えてから臨んでください。復元の順序は、グローバルオブジェクト、データベース作成、本体の順です。

バックアップ運用を内製で持つ範囲と外部へ委託する範囲の決め方

取得の自動化と監視までは内製で持てます。スクリプトは短く、失敗検知も監視基盤に載せるだけだからです。取得状況を担当者以外にも確認させるなら、読み取り専用ロールで参照口だけを開ける手もあります。手順はPostgreSQL MCPサーバーの構成と権限設計にまとめました。判断が分かれるのは復旧訓練と、方式そのものの見直しでしょう。年に数回しか実施しない作業に社内の練度は溜まりにくく、担当者が変わると手順書だけが残ります。

訓練の設計と立ち会い、そして更新量の増加に合わせた方式の再検討は、外部に置いたほうが結果的に安く付く領域です。開発を委託した相手がそのまま保守も見る体制なら、スキーマ変更のたびに復旧手順を追随させられます。この範囲の請け方は保守運用 / 内製化支援にまとめています。内製で完結させたい場合も、初回の設計と一度目の訓練だけ伴走してもらい、二度目から自走する進め方が現実的です。

よくある質問

pg_dumpは本番稼働中に実行しても大丈夫ですか?

読み書きをロックしないため、稼働中の実行は想定された使い方です。ただし取得中は長時間のトランザクションが開いたままになり、その間に不要になった行を自動清掃の仕組みが回収できません。大きなデータベースで日中に流すと、肥大化の原因になります。負荷の低い時間帯に寄せ、並列指定を使うなら接続上限を先に確認してください。

pg_dumpだけでPITRの代わりになりませんか?

なりません。pg_dumpが残すのは取得を開始した時点の一貫した断面だけで、その後の更新履歴を持たないためです。1時間おきに取れば損失は最大1時間になりますが、任意の時刻を指定して戻すことはできません。時刻指定が要件なら、ベースバックアップとWALアーカイブの組み合わせを選んでください。

増分バックアップを取れば容量を減らせますか?

取得ごとの容量は減りますが、保管総量はそれほど減りません。復元には連鎖する全世代が要り、途中の1世代でも失うとその後が使えなくなるからです。加えて合成の工程が入るぶん復旧時間は伸びます。復旧時間の目標が厳しい場合は、増分の世代数を絞ってフルの頻度を上げる設計にしてください。

WALアーカイブの保持期間はどれくらいにすべきですか?

最も古いベースバックアップの取得時点より前のWALは、そのバックアップから復旧する用途では使いません。逆に言えば、保持しているベースバックアップのうち最も古いものの時点以降は、すべて残す必要があります。ベースを週次で取るなら、WALは最低でも2週間分を持たせる設計が扱いやすいでしょう。

復元したデータベースが取得元より遅いのはなぜですか?

統計情報が引き継がれていない可能性が高いです。18でpg_dumpに統計を含める指定が入りましたが、既定では含まれません。復元直後にANALYZEを流し、実行計画が想定どおりか確かめてください。それでも遅い場合は、共有バッファなどサーバ側の設定が移行先で既定値に戻っていないかを見てください。

関連記事

お気に入りに入れた記事の一覧

この記事は以下の記事からリンクされています

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.10.09 テックブログ IDCFクラウド(IDCフロンティア)不正アクセス・ランサムウェア:影響先・復旧・データは戻るか
  2. 2024.11.08 テックブログ OpenAPI GeneratorでJavaコードを自動生成する方法|CLI導入からSpring・ライブラリ選択まで
  3. 2026.10.09 テックブログ ニッスイのサイバー攻撃で日水物流の入出荷停止|委託先クラウド障害に荷主が備える手順
  4. 2026.10.08 テックブログ 大阪公立大学のランサムウェア被害と仮想化基盤の停止|全授業休講に至った経緯とバックアップを守る設定
  5. 2026.10.09 テックブログ 京王電鉄のランサムウェア被害とグループ共通基盤:決済・ポイント・予約が止まった範囲と遮断の初動

RELATED POSTS 関連記事

目次