📝 [PostgreSQL] レプリケーション構成で増え続ける WAL アーカイブをどう整理する?
😊 はじめに
こんにちは。
私が開発とサーバー運用を担当している「XD.GROWTH」はPostgreSQLをストリーミングレプリケーション構成で利用しています。この記事では、PostgreSQL のレプリケーション運用における アーカイブされた WAL ファイル(WAL アーカイブ)の管理・削除方法 について、実運用で役に立つ実践的な手法を解説します。
対象読者は以下を想定しています。
- PostgreSQLの運用経験がある方
- レプリケーション構成で運用に課題を抱えている方
- Linux環境でのシェルスクリプトの基礎知識がある方
本記事は可能な限り端折らず分かりやすく説明しますが、用語や詳細は必要に応じてPostgreSQL公式ドキュメントなどを参照してください。
本記事のスコープ
本記事は PITR(Point-In-Time Recovery)バックアップの設計 が主題ではなく、ストリーミングレプリケーション運用 で増え続ける アーカイブされた WAL ファイル(WAL アーカイブ) を「スタンバイの取り込み状況に合わせて安全に削除する」ことに焦点を当てています。PITR目的の世代管理(保管期間・オフサイト保管など)は本稿の対象外です。
⚙️ 動作環境(参考)
| 項目 | 値 |
|---|---|
| OS | Rocky Linux 9.x |
| DBMS | PostgreSQL 17.x |
| サーバー台数 | 2台(プライマリ+スタンバイ) |
📦 WAL アーカイブ(アーカイブされた WAL ファイル)とは
WAL アーカイブ は、データベース更新情報の WAL(Write-Ahead Log)を、外部ディレクトリへ永続化したファイル群を指します(俗に「アーカイブログ」とも呼ばれます)。
- PostgreSQLでは更新内容はWAL(Write-Ahead Log)として記録されます。WALはディスク上では固定サイズ(通常 16MB)でセグメントファイルとして保存され、これを WALファイル と呼びます。
- デフォルトの設定では WAL アーカイブの生成は無効です。
- 有効にすると、WALファイルがローテーションされる際に外部ディレクトリへコピー(保存)されます。
✅ WAL アーカイブを有効にする設定
-
postgresql.confに以下の設定を追加します。archive_mode = on archive_command = 'cp %p /path/to/archive/%f'
本記事では「生成された WAL アーカイブをどうやって安全に削除するか」に焦点を当てています。
❗ なぜ WAL アーカイブが必要なのか?
WAL アーカイブが有効 / 無効にかかわらず、プライマリでは${PGDATA}/pg_wal配下にWALファイルを保持します。但し、保持できるデータ量はmax_wal_sizeなどで制限され超過した場合、古いWALファイルから削除されます。
レプリケーション構成では通常はスタンバイへ即時にWALが転送され同期されるので、WAL アーカイブが無くても運用可能です。
しかし、以下のような非常事態ではWALの転送に遅延が発生します:
- プライマリで大量データインポートが行われる
- スタンバイが停止する(メンテナンスでの計画停止、メモリ不足などでのダウン等)
- ネットワーク分断によりスタンバイとの通信ができない
これらの状況が長時間続くと、スタンバイが必要なWALファイルがプライマリの${PGDATA}/pg_walから削除されてしまいデータの同期が取れなくなるという状況に陥る可能性があります。
レプリケーション構成の復旧(スタンバイの再同期)やポイントインタイムリカバリ(PITR)を考えると、WALファイルを別ディレクトリにアーカイブしておくことは重要です。
🔍 なぜ WAL アーカイブファイルの削除が必要か?
アーカイブされた WAL ファイルは自動では削除されないため、放置するとアーカイブ先ディスクが一杯になり運用に支障をきたします。したがって、不要になった WAL アーカイブを安全に削除する運用が必要です。
PostgreSQL では WAL アーカイブの削除のために以下を用意しています:
-
pg_archivecleanupコマンド:指定したWALファイルを含め、それ以前の WAL アーカイブを削除するユーティリティ -
archive_cleanup_command:適用されたWALファイルなど不要になった WAL アーカイブを削除するためのコマンド設定項目
🛠️ pg_archivecleanup のポイント
- アーカイブディレクトリとファイル名を引数に指定することで WAL アーカイブを削除します。
- 削除対象は、指定したファイルより古い WAL アーカイブになります。
-
archive_cleanup_commandに設定すれば、WALファイルを取り込んだタイミングで不要になった WAL アーカイブをリアルタイムに削除できます。 -
(重要) レプリケーション構成の場合 プライマリで指定された
archive_cleanup_commandは実行されません。
🧭 よくある(しかし問題のある)削除方法と課題
ここでは WAL アーカイブの削除についての運用で見かける手法と、その問題点を整理します。
① ネットワーク共有(NFS等)
-
アーカイブディレクトリをNFSなどで共有し、プライマリ/スタンバイが同一の WAL アーカイブを参照するようにする。
-
スタンバイの
archive_cleanup_commandへの設定例:archive_cleanup_command = 'pg_archivecleanup /path/to/archive %r'
問題点
- 共有サーバー(ストレージ)を別途用意するコストが発生する
- NFS等を利用する場合は信頼性やセキュリティ面の懸念がある
- スタンバイが複数ある場合、他のスタンバイではまだ必要なWALファイルを誤って削除してしまう可能性がある
② SSH経由でプライマリにて pg_archivecleanup を実行する
-
スタンバイの
archive_cleanup_commandの設定例:archive_cleanup_command = 'ssh -i /path/to/key -o BatchMode=yes postgres@primary.example.com "pg_archivecleanup /path/to/archive %r"'
問題点
- SSH接続の失敗(鍵問題やネットワーク)で削除が行われないリスクがある
- スタンバイが複数ある場合、他のスタンバイではまだ必要なWALファイルを誤って削除してしまう可能性がある
③ 定期的にタイムスタンプが過去のファイルを削除
-
プライマリにて、WAL アーカイブのタイムスタンプを調べタイムスタンプが閾値以上の過去のファイルを削除する
-
archive_cleanup_commandは設定せず、削除処理を行うスクリプトを用意し、cronなどで定期的に実行する -
タイムスタンプが3日以上過去のファイルを削除するコマンド:
find /path/to/archive -mtime +3 -type f -delete
問題点
- 削除対象のWALファイルがスタンバイに取り込まれたかを判断することが出来ない
- このため、WALファイルを残す期間を長くする必要がありディスクを圧迫する可能性がある
✅ より安全かつ現実的な解決策(本番向け推奨)
では、どうすれば良いでしょう?
私たちが考える、安全性とコストのバランスが良い運用手順について説明します。
ポイントはプライマリ側で一元的に削除判断を行い、スタンバイの取り込み状況を参照して安全に削除することです。
仕組みの概要
- プライマリ上に削除用スクリプトを用意し、cronなどで定期実行する。
- スクリプトは実行前に以下のチェックを行う:
- 実行ユーザーが
postgresであること - 当該サーバーがプライマリであること(
SELECT pg_is_in_recovery()がfalseを返す)
- 実行ユーザーが
- スタンバイが複数存在する場合を考慮し、全スタンバイに対して取り込んだ最新のWALファイル名を取得する
- SSH経由でスタンバイにて
pg_controldataコマンドを実行します - スタンバイが複数存在する場合は、取得したファイル名から タイムスタンプが最も古いもの を削除対象とする
- SSH経由でスタンバイにて
- 3.で取得したファイル名を
pg_archivecleanupの引数に指定して実行する(安全側に寄せる)
サンプル:スタンバイで最新取り込みWALファイル名を取得するコマンド例
-
ssh経由でスタンバイにて
pg_controldataコマンドを実行します -
pg_controldataコマンドはフルパスで指定しますssh -o StrictHostKeyChecking=no -i /path/to/key postgres@standby.example.com \ "/path/to/pgsql/bin/pg_controldata -D /var/lib/pgsql/data" | \ grep "Latest checkpoint's REDO WAL file" | awk '{print $6}'-
StrictHostKeyChecking=noは利便性のためのオプションです。セキュリティを重視する本番環境では、事前にssh-keyscanなどでホスト鍵を登録しておくことを推奨します。 -
取得したファイル名は
0000000100000000000000A1のような形式になります。
-
サンプル:プライマリでの pg_archivecleanup 実行例
-
以下では
0000000100000000000000A1を(含む)過去の WAL アーカイブを削除します。 -
pg_archivecleanupコマンドはフルパスで指定します。/path/to/pgsql/bin/pg_archivecleanup /path/to/archive 0000000100000000000000A1
🧾 「WAL アーカイブの削除手法」比較表
| 手法 | 実行箇所 | 主なメリット | 主なデメリット / 注意点 |
|---|---|---|---|
| NFS等の共有ストレージ | 共通ストレージ | 実装が単純(全ノードが同一の参照先) | 共有ストレージの設置コスト/運用コスト、信頼性・セキュリティ・ネットワーク負荷の懸念。複数スタンバイ時に同期が遅いノードの判別が困難。 |
SSHでプライマリの pg_archivecleanup を実行 |
プライマリ | プライマリで削除できる | SSH接続失敗で削除されない。複数スタンバイ時に同期が遅いノードの判別が困難。 |
| 定期的に過去のファイルを単純に削除 | プライマリ | 実装が単純(ワンライナーも可) | スタンバイの同期情報が判別できない。ディスクが圧迫される可能性あり |
プライマリで定期的にスタンバイの取り込み状態を参照して pg_archivecleanup 実行(推奨) |
プライマリ | 削除判断を一元化できる。必要なファイルのみ残せる。誤削除リスクほぼ無し。 | スクリプト作成・エラー監視の実装が必要 |
🔐 セキュリティと運用の補足
- SSH鍵管理は慎重に行いましょう(専用鍵、適切なパーミッション、必要ならJumpホスト経由など)。
- スクリプトは以下を満たすように実装しましょう
- 適切な実行権限(postgresユーザーのみ実行可能にする)
- ログ出力とログファイルの適切パーミッション設定
- SSH接続をする処理などはエラー時のリトライ
- 異常終了時のアラートメールの送信
- テスト環境で十分に検証してから本番へ適用しましょう
-
pg_archivecleanupコマンドは--dry-runオプションを付けて、想定どおりの動作になるかを確認
-
- アーカイブ先のバックアップポリシー(保管期間、圧縮、オフサイト保管)を明確にしましょう
📌 まとめ
- WAL アーカイブは必要だが、自動削除されないため運用で管理が必要です。
-
pg_archivecleanupコマンド と 設定項目archive_cleanup_commandを理解し、削除基準を誤らない運用設計が重要です。 - 「プライマリで一元的に判定して
pg_archivecleanupを定期実行する」方法を推奨します。コストを抑えつつ安全に不要ファイルを削除できると考えます。 - 実装の際はSSH鍵管理、ログ・監視、テストは欠かさないようにしましょう。
最後まで読んでいただきありがとうございました ![]()
PostgreSQL レプリケーション運用での WAL アーカイブの取り扱いについて、この記事が参考になれば幸いです。 ![]()