本番環境でPostgreSQLを管理するデータベース管理者(DBA)やDevOpsエンジニアにとって、目標復旧時点(RPO)をゼロに近づけることは最優先事項です。PostgreSQLの災害復旧およびポイントインタイムリカバリ(PITR)機能の中核を成すのが、Write-Ahead Logging(WAL)です。WALは、データファイルに書き込まれる前にトランザクションを記録することでACID準拠を保証しますが、WALのアーカイブは、長期的なバックアップとレプリケーションのためにこれらのログを保存するメカニズムです。
しかし、WALアーカイブの設定は「一度設定すれば終わり」というものではありません。設定ミスやサイレント障害、アーキテクチャの理解不足は、壊滅的なデータ損失、スプリットブレインシナリオ、あるいはデータベース全体の停止につながる可能性があります。
この包括的なガイドでは、PostgreSQLのWALアーカイブのアーキテクチャを解説し、データ損失につながる最も一般的な落とし穴を特定し、データベースの回復力を維持するための本番環境向けのベストプラクティスを概説します。
PostgreSQL WALアーキテクチャの理解
落とし穴を掘り下げる前に、PostgreSQLがどのようにトランザクションログを処理するかを理解することが不可欠です。
PostgreSQLは、すべての変更をpg_walディレクトリ(バージョン10以前はpg_xlog)にあるWALセグメント(デフォルトは16MB)に書き込みます。すべてのトランザクションは、ログシーケンス番号(LSN)によってマークされ、順次記録されます。
WALセグメントがいっぱいになると、PostgreSQLは新しいセグメントに切り替えます。pg_walディレクトリが無限に肥大化するのを防ぐため、PostgreSQLはクラッシュリカバリやレプリケーションに不要になった古いWALセグメントを再利用または削除します。
WALアーカイブは、この再利用プロセスに介入します。archive_modeが有効な場合、PostgreSQLはユーザー定義のarchive_commandを実行(またはPostgreSQL 15以降ではarchive_libraryを利用)し、完了したWALセグメントが削除または上書きされる前に、安全なセカンダリの場所にコピーします。
ポイントインタイムリカバリ(PITR)を実行するには、以下の2つのコンポーネントが必要です。
1. 有効なベースバックアップ。
2. ベースバックアップの時点から目標の復旧時点までの、途切れることのないアーカイブ済みWALファイルのチェーン。
このWALチェーンが途切れると、PITRは失敗します。
本番環境向けのWALアーカイブ設定
WALアーカイブを有効にするには、postgresql.confファイルを変更する必要があります。基本的な設定には、wal_levelの設定、archive_modeの有効化、およびarchive_commandの定義が必要です。
# postgresql.conf
wal_level = replica # アーカイブには 'replica' または 'logical' が必要
archive_mode = on # アーカイバプロセスを有効化
archive_command = 'test ! -f /mnt/nfs/archive/%f && cp %p /mnt/nfs/archive/%f'
archive_timeout = 600 # 10分ごとに強制的にWALスイッチを実行
archive_commandにおいて:
* %p はアーカイブ対象のWALファイルへのフルパスを表します。
* %f はWALファイルのファイル名を表します。
上記の設定は単純に見えますが、エンタープライズ環境で単純なシェルコマンドに依存することは重大なリスクを伴います。
WALアーカイブにおける一般的な落とし穴
落とし穴1:archive_commandの「サイレント成功」
PostgreSQLはarchive_commandの終了コードに完全に依存しています。コマンドが0を返すと、PostgreSQLはWALファイルが安全にアーカイブされたと見なし、元のファイルを再利用します。
よくある間違いは、データが永続ストレージに安全にフラッシュされていなくても0を返すコマンドを使用することです。例えば、単純なcpコマンドは、データが宛先サーバーのOSページキャッシュに到達した時点で成功を返す場合があります。キャッシュがディスクにフラッシュされる前に宛先サーバーの電源が切れると、WALファイルは失われますが、PostgreSQLはすでにローカルコピーを削除してしまっています。
リスク: WALチェーンの断絶とPITRの実行不能。これは災害復旧シナリオの際に初めて発覚します。
緩和策: アーカイブスクリプトが同期書き込みを強制するようにします。標準のシェルコマンドを使用する場合は、データのフラッシュを保証するツールを使用するか、転送後にファイルサイズとチェックサムを検証するラッパースクリプトを作成してください。
落とし穴2:pg_walパーティションの枯渇(WAL肥大化)
ネットワーク障害、権限の誤り、または宛先ディスクのフルなどの理由でarchive_commandが失敗(非ゼロの終了コードを返す)した場合、PostgreSQLはWALファイルをpg_walディレクトリに保持し、コマンドを無期限に再試行します。
これにより、アーカイブされていないWALが削除されるのを防ぎデータ損失を回避できますが、深刻な可用性のリスクが生じます。pg_walディレクトリが100%まで埋まったパーティションにある場合、PostgreSQLはPANICを発行してクラッシュします。空き容量が確保されるまで、データベースは再起動しません。
リスク: pg_walパーティションのフルによるデータベース全体のダウンタイム。
緩和策:
1. pg_walは常に専用のディスクパーティションに配置する。
2. pg_walディレクトリのサイズを厳格に監視する。
3. pg_stat_archiverビューを監視し、失敗しているアーカイブコマンドを即座に検知する。
落とし穴3:不完全なベースバックアップ
ベースバックアップは、バックアッププロセス中に生成されたWALファイルなしでは役に立ちません。ファイルシステムレベルのスナップショットを取得する場合や、WALをストリーミングせずに(-X streamなしで)pg_basebackupを使用する場合は、バックアップの開始から終了までの間に生成されたWALファイルが正常にアーカイブされていることを確認する必要があります。
アーカイバが遅延または失敗しており、それらの特定のWALファイルが失われた場合、ベースバックアップを一貫した状態に復元することはできません。
リスク: 破損した、または復旧不可能なベースバックアップ。
緩和策: pg_basebackup -X streamを使用して必要なWALファイルをバックアップペイロード自体に含めるか、ベースバックアップとWALセグメント間の依存関係を自動的に管理するエンタープライズバックアップソリューションを使用してください。
落とし穴4:タイムラインの混乱とスプリットブレインシナリオ
スタンバイサーバーがプライマリに昇格すると、PostgreSQLは「タイムラインID」(WALファイル名の最初の部分、例:0000000200000001000000A4)をインクリメントします。これにより、新しいプライマリが古いプライマリのWAL履歴を上書きするのを防ぎます。
しかし、古いプライマリが適切にフェンシングされずに誤って起動された場合(スプリットブレインシナリオ)、古いタイムラインを使用して同じアーカイブ場所にWALファイルをプッシュしようとする可能性があります。archive_commandが盲目的にファイルを上書きするように設定されていると、アーカイブ・リポジトリが破損する可能性があります。
リスク: WALファイルの上書き、アーカイブの破損、およびデータベースの復旧不能。
緩和策: archive_commandは、既存のファイルを決して上書きしてはなりません。前述の基本設定で、ファイルが既に存在する場合は明示的に失敗させるためにtest ! -f /mnt/nfs/archive/%fを使用したことに注目してください。
データ損失リスクの緩和:本番環境のベストプラクティス
PostgreSQLのアーカイブ戦略を強化するために、以下のベストプラクティスを実装してください。
1. アーカイバプロセスをネイティブに監視する
PostgreSQLは、アーカイブプロセスの成功と失敗を追跡する組み込みビューpg_stat_archiverを提供しています。このビューを監視スタック(Prometheus、Datadog、Zabbixなど)に統合する必要があります。
SELECT
archived_count,
last_archived_wal,
last_archived_time,
failed_count,
last_failed_wal,
last_failed_time,
stats_reset
FROM pg_stat_archiver;
設定すべきアラートのしきい値:
* failed_countが増加した場合にアラートを出す。
* now()とlast_archived_timeの差がRPOのしきい値(例:15分)を超えた場合にアラートを出す。ただし、archive_timeoutが設定されていない限り、トラフィックの少ないデータベースでは自然に遅延が発生する可能性があることに注意してください。
2. archive_timeoutを活用する
書き込みボリュームが少ないデータベースでは、16MBのWALファイルがいっぱいになるまでに数時間かかる場合があります。いっぱいになるまでアーカイブは行われません。サーバーがクラッシュしてローカルディスクが失われると、数時間分のトランザクションが失われます。
archive_timeout = 600(10分)を設定すると、WALファイルがいっぱいでなくても、PostgreSQLは強制的に新しいWALファイルに切り替えて現在のファイルをアーカイブします。これにより、部分的にしか埋まっていないWALファイルによるストレージ使用量のわずかな増加と引き換えに、RPOが10分を超えないことが保証されます。
3. archive_libraryへの移行(PostgreSQL 15以降)
従来、archive_commandはWALファイルごとに新しいシェルプロセスを生成していました。毎分数百のWALファイルを生成する高スループット環境では、シェルプロセスのフォークによるオーバーヘッドがパフォーマンスのボトルネックとなります。
PostgreSQL 15ではarchive_libraryパラメータが導入され、動的にロードされるCモジュールによってWALアーカイブを処理できるようになりました。これにより、シェルフォークのオーバーヘッドが排除され、より堅牢で高性能なアーカイブメカニズムが提供されます。PostgreSQL 15以上を使用している場合は、カスタムアーカイブモジュールをサポートするバックアップツールを探してください。
4. ポイントインタイムリカバリを定期的にテストする
テストされていないバックアップはバックアップではなく、単なる「願い」です。WALアーカイブが正しく機能していること、WALチェーンが途切れていないこと、ベースバックアップが一貫していることを確認する唯一の方法は、定期的な自動PITRテストを実行することです。
一時的なインスタンスを立ち上げ、ベースバックアップを復元し、アーカイブから取得するようにrestore_commandを設定し、特定のタイムスタンプまでリカバリします。データベースが一貫した状態に達し、接続を受け入れられることを確認してください。
CloudSaveによるエンタープライズバックアップとリカバリ
archive_commandのためのカスタムシェルスクリプトの管理、WALの重複排除、トランザクションログの安全なオフサイトストレージの確保は、ITチームにとってすぐに運用上の負担となります。
ここで、CloudSaveがエンタープライズPostgreSQL環境に大きな価値を提供します。CloudSaveは、PostgreSQLのネイティブバックアップおよびWALアーカイブAPIと直接統合され、前述の手動による落とし穴を排除します。
壊れやすいbashスクリプトを書く代わりに、CloudSaveは以下を実現する堅牢なエージェントベースまたはエージェントレスの統合を提供します:
* 配信の保証: 標準のシェルコマンドを、安全なオフサイトまたはクラウドストレージへの検証済み・チェックサム検証済みの転送に置き換えます。
* WAL肥大化の防止: pg_walディレクトリを積極的に監視し、パーティションが枯渇するずっと前に管理者に警告します。
* PITRの自動化: 直感的なインターフェースを通じてポイントインタイムリカバリを簡素化します。復旧したい正確な分を指定するだけで、CloudSaveが正しいベースバックアップを自動的に取得し、その状態に達するために必要なWALファイルの正確なシーケンスをストリーミングします。
* タイムラインの処理: PostgreSQLのタイムライン履歴をインテリジェントに管理し、フェイルオーバーやスプリットブレインシナリオがバックアップリポジトリを破損させないようにします。
WAL管理の重労働をCloudSaveにオフロードすることで、DBAはクエリの最適化やデータベースのパフォーマンスに集中でき、RPOおよびRTOのSLAがエンタープライズグレードのプラットフォームによって保護されているという安心感を得ることができます。
結論
PostgreSQLのWALアーカイブは、データベース災害復旧のバックボーンです。あるディレクトリから別のディレクトリへファイルをコピーするという概念は単純に見えますが、サイレント障害、ディスク枯渇、タイムラインの乖離といったエッジケースは、データの整合性に深刻なリスクをもたらします。
pg_walのアーキテクチャを理解し、破壊的なarchive_command設定を厳格に避け、pg_stat_archiverを監視し、CloudSaveのようなエンタープライズバックアッププラットフォームを活用することで、ハードウェア障害、人為的ミス、壊滅的な停止に耐え、コミットされたトランザクションを一切失うことなく生き残れる、回復力のあるPostgreSQLインフラストラクチャを構築できます。
データ損失につながるPostgreSQL WALアーカイブの一般的な落とし穴を発見してください。専門的なDBAのベストプラクティス、設定のヒント、およびエンタープライズデータベースのための信頼性の高いポイントインタイムリカバリ(PITR)を確保する方法を学びましょう。