この記事では、Rocky Linux 9.4 / Ubuntu 24.04 LTS上でPostgreSQL 16を対象に、WALアーカイブの有効化からpg_basebackupによるベースバックアップの取得、recovery.signalを使ったPITR実行までを実機コマンドつきで解説します。pg_dumpとPITRをどう使い分けるかも整理しているので、バックアップ設計を見直したい方にも参考になります。
この記事のポイント
・WALアーカイブを有効にして変更ログを継続保存する
・pg_basebackupで定期的なベースバックアップを取得する
・recovery.signalを置き、recovery_target_timeで任意時点に復元
・pg_stat_archiverでアーカイブの失敗を常時監視する
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
pg_dumpとWALアーカイブは何が違うのか
PostgreSQLのバックアップには大きく2種類あります。・論理バックアップ(pg_dump / pg_dumpall):SQLの形でスキーマとデータをエクスポート。バックアップ取得時点のスナップショットしか残らない
・物理バックアップ+WALアーカイブ:データファイルをそのままコピーし、その後の変更をWALセグメントで継続保存。任意の時刻・LSNまでの巻き戻しが可能
論理バックアップは「昨夜3:00のダンプしかない」状態になりがちで、翌朝10:00に発生したミスには無力です。WALアーカイブを組み合わせた物理バックアップなら「10:00の5分前まで戻す」ことができます。
PITRを実現するには以下の3点が揃う必要があります。
・
wal_level = replica 以上(PostgreSQL 16のデフォルト値)・
archive_mode = on と archive_command の設定(WALをアーカイブ先へコピー)・定期的なベースバックアップ(pg_basebackupで取得)
WALアーカイブを有効にする(archive_mode・archive_commandの設定)
1. アーカイブ保存先ディレクトリを作成する
まずpostgresユーザーが書き込めるディレクトリを用意します。# mkdir -p /var/lib/pgsql/wal_archive # chown postgres:postgres /var/lib/pgsql/wal_archive # chmod 700 /var/lib/pgsql/wal_archive
2. postgresql.confにアーカイブ設定を追加する
postgresql.confを編集します(Rocky Linux 9ではデフォルト/var/lib/pgsql/16/data/postgresql.conf)。# vi /var/lib/pgsql/16/data/postgresql.conf wal_level = replica # デフォルト値。replicaまたはlogical archive_mode = on # アーカイブを有効化 archive_command = 'test ! -f /var/lib/pgsql/wal_archive/%f && cp %p /var/lib/pgsql/wal_archive/%f' # %p : WALファイルのフルパス %f : WALファイル名のみ
・
test ! -f .../wal_archive/%f:同名ファイルが既存の場合は上書きしない(二重コピーを防ぐ)・
&& cp %p .../wal_archive/%f:存在しない場合のみコピー・コマンドが終了コード0を返したとき「アーカイブ成功」とPostgreSQLが判断する
3. PostgreSQLを再起動して設定を反映する
archive_mode の変更はリロード(pg_reload_conf())では反映されないため、再起動が必要です。# systemctl restart postgresql-16 # systemctl status postgresql-16 * postgresql-16.service - PostgreSQL 16 Database Server Loaded: loaded (/usr/lib/systemd/system/postgresql-16.service; enabled; preset: disabled) Active: active (running) since Mon 2026-09-22 09:45:02 JST; 5s ago
# su - postgres -c "psql -c "SHOW archive_mode;"" archive_mode -------------- on (1 row)
pg_basebackupでベースバックアップを取得する
アーカイブを有効にしただけでは復旧の起点(ベースバックアップ)がありません。定期的にpg_basebackupを実行し、直近のベースバックアップからWALを当てる設計にします。1. ベースバックアップ保存先を用意する
# mkdir -p /var/lib/pgsql/backup # chown postgres:postgres /var/lib/pgsql/backup # chmod 700 /var/lib/pgsql/backup
2. pg_basebackupを実行する
# su - postgres $ pg_basebackup -D /var/lib/pgsql/backup/base_20260922 --checkpoint=fast -Xs -P 24390/24390 kB (100%), 1/1 tablespace
・
-D /path:バックアップ出力先ディレクトリ・
--checkpoint=fast:チェックポイントを即時実行してバックアップ開始を速くする・
-Xs:ストリーミングでWALをバックアップに同梱(-x は非推奨)・
-P:進捗表示3. バックアップ後のファイルを確認する
$ ls -la /var/lib/pgsql/backup/base_20260922/ | head -8 total 84 drwx------. 21 postgres postgres 4096 Sep 22 10:31 . drwx------. 3 postgres postgres 47 Sep 22 10:31 .. -rw-------. 1 postgres postgres 224 Sep 22 10:31 backup_label -rw-------. 1 postgres postgres 88 Sep 22 10:31 backup_manifest drwx------. 9 postgres postgres 91 Sep 22 10:31 base drwx------. 2 postgres postgres 4096 Sep 22 10:31 global -rw-------. 1 postgres postgres 5065 Sep 22 10:31 postgresql.conf $ ls -la /var/lib/pgsql/wal_archive/ | head -8 total 49156 drwxr-x---. 2 postgres postgres 4096 Sep 22 10:58 . drwx------. 5 postgres postgres 111 Sep 22 10:31 .. -rw-------. 1 postgres postgres 16777216 Sep 22 10:31 000000010000000000000001 -rw-------. 1 postgres postgres 16777216 Sep 22 10:31 000000010000000000000002 -rw-------. 1 postgres postgres 16777216 Sep 22 10:58 000000010000000000000003
recovery.signalとリカバリターゲットを設定する(PostgreSQL 12以降)
PostgreSQL 12からrecovery.confが廃止され、リカバリパラメータはpostgresql.confに書くように変わりました。データディレクトリにrecovery.signalという空ファイルを置くことがリカバリモード開始のスイッチになります。ここでは「2026年9月22日11:00に誤って大規模DELETEが実行された」ケースを想定し、10:55時点に戻す手順を示します。
1. 現在のデータディレクトリを退避する
# systemctl stop postgresql-16 # mv /var/lib/pgsql/16/data /var/lib/pgsql/16/data.broken
2. ベースバックアップをデータディレクトリにコピーする
# cp -a /var/lib/pgsql/backup/base_20260922 /var/lib/pgsql/16/data # chown -R postgres:postgres /var/lib/pgsql/16/data # chmod 700 /var/lib/pgsql/16/data
3. postgresql.confにリカバリパラメータを追加する
# vi /var/lib/pgsql/16/data/postgresql.conf # --- PITRパラメータ追加 --- restore_command = 'cp /var/lib/pgsql/wal_archive/%f %p' recovery_target_time = '2026-09-22 10:55:00' recovery_target_timezone = 'Asia/Tokyo' recovery_target_action = 'promote'
・
restore_command:WALファイルをアーカイブから取り込むコマンド(%f=ファイル名・%p=コピー先パス)・
recovery_target_time:この時刻の直前のコミットまでWALを再生して停止・
recovery_target_action = 'promote':目標到達後に自動昇格して通常運用へ移行(pauseにすれば手動で確認もできる)4. recovery.signalファイルを作成する
# su - postgres -c "touch /var/lib/pgsql/16/data/recovery.signal" # ls -la /var/lib/pgsql/16/data/recovery.signal -rw-------. 1 postgres postgres 0 Sep 22 11:15 /var/lib/pgsql/16/data/recovery.signal
PITRの実行ログと完了確認
1. PostgreSQLを起動してリカバリを開始する
# systemctl start postgresql-16
2. ログでリカバリの進捗を追う
# tail -f /var/lib/pgsql/16/data/log/postgresql-Mon.log 2026-09-22 11:20:03.412 JST [1234] LOG: starting point-in-time recovery to 2026-09-22 10:55:00+09 2026-09-22 11:20:03.501 JST [1234] LOG: restored log file "000000010000000000000001" from archive 2026-09-22 11:20:04.100 JST [1234] LOG: restored log file "000000010000000000000002" from archive 2026-09-22 11:20:04.318 JST [1234] LOG: recovery stopping before commit of transaction 742, time 2026-09-22 10:55:47.441512+09 2026-09-22 11:20:04.320 JST [1234] LOG: pausing at the end of recovery 2026-09-22 11:20:04.322 JST [1234] LOG: database system is ready to accept read only connections 2026-09-22 11:20:04.330 JST [1234] LOG: selected new timeline ID: 2 2026-09-22 11:20:04.350 JST [1234] LOG: archive recovery complete
archive recovery complete が確認できれば完了です。recovery.signal は自動的に削除され、通常の読み書き可能な状態に移行します。3. データが正しく戻ったか確認する
$ psql -U postgres -c "SELECT count(*) FROM orders WHERE order_date < '2026-09-22 11:00:00';" count ------- 24387 (1 row)
promoteにしていたため、pg_wal_replay_resume()を手動で実行しなくても自動で通常運用へ移行しています。トラブルシュート
アーカイブが進まない(WALファイルが積み上がる)
archive_commandが失敗するとWALはpg_walディレクトリに溜まり続け、ディスクを圧迫します。まずpg_stat_archiverで失敗件数を確認します。$ psql -U postgres -c "SELECT archived_count, last_archived_wal, failed_count, last_failed_wal FROM pg_stat_archiver;" archived_count | last_archived_wal | failed_count | last_failed_wal ----------------+-------------------------------------+--------------+---------------------------------------- 12 | 000000010000000000000003 | 2 | 000000010000000000000004
# su - postgres -c "test ! -f /var/lib/pgsql/wal_archive/000000010000000000000004 && cp /var/lib/pgsql/16/data/pg_wal/000000010000000000000004 /var/lib/pgsql/wal_archive/000000010000000000000004" # echo 0 0
・アーカイブディレクトリがディスク不足でフル
・postgresユーザーの書き込み権限がない
・archive_commandのパスが誤っている(再起動後は反映されるがreloadでは反映されない)
restore_commandが「No such file or directory」で失敗する
PITRリカバリ時にアーカイブから取り込めない場合、ログに以下のようなエラーが出ます。2026-09-22 11:21:00.100 JST [1234] LOG: could not restore file "000000010000000000000005" from archive: return code 1
restore_command = 'cp /var/lib/pgsql/wal_archive/%f %p 2>/tmp/restore_err.log'
recovery_target_timeの時刻に止まらない
recovery_target_timeのタイムゾーンがズレていると正しい時刻に止まりません。必ずrecovery_target_timezone = 'Asia/Tokyo'を明示するか、UTC表記(例: '2026-09-22 01:55:00+00')で指定します。本記事のまとめ
| やりたいこと | コマンド・設定 |
|---|---|
| WALアーカイブを有効化する | archive_mode = on と archive_command = '...' をpostgresql.confに追加後に再起動 |
| ベースバックアップを取得する | pg_basebackup -D /path/to/backup --checkpoint=fast -Xs -P |
| アーカイブ状況を確認する | SELECT archived_count, failed_count FROM pg_stat_archiver; |
| リカバリ目標時刻を指定する | postgresql.confに recovery_target_time = '2026-09-22 10:55:00' を追加 |
| リカバリモードを開始する | touch /var/lib/pgsql/16/data/recovery.signal 後にPostgreSQLを起動 |
| リカバリ完了後に通常運用へ移行する | recovery_target_action = 'promote' で自動昇格 / または手動で SELECT pg_wal_replay_resume(); |
| タイムゾーンを明示してリカバリする | postgresql.confに recovery_target_timezone = 'Asia/Tokyo' を追加 |
PostgreSQLの実運用は「Linux基盤の設計」が土台になります
WALアーカイブやPITRを安心して運用するには、Linuxサーバーのファイルシステム・ストレージ設計・サービス管理を体系的に理解することが重要です。独学で断片的に覚えるより、現場で実際に使われる設計パターンを一度体系的に身につける方が、障害時にも慌てず対応できます。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:MySQLのイベントスケジューラーを使ってデータ定期削除・集計を自動化する手順|CREATE EVENTの実践
- この記事の属するカテゴリ:データーベース管理へ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます