午前2時14分、緊急アラートの鳴動
私のスマートフォンの「クリティカル・アラート」は、本番環境での緊急事態(3-alarm production fires)のために特別に設定した、不快で高音のサイレンです。先週火曜日の午前2時14分、そのサイレンが鳴り響きました。私は寝ぼけ眼でデスクに這い寄り、プライマリのPostgreSQLノードが完全に無反応になっているのを確認しました。クラウドプロバイダーのハードウェア障害により、基盤となるEBSボリュームが破壊され、データベースもろとも消失してしまったのです。
最初に頭をよぎったのはパニックではなく、冷徹な計算でした。当社のcronジョブは毎晩深夜0時に pg_dump を実行しています。今は午前2時14分.そのダンプから復元するということは、134分間の顧客取引データを失うことを意味します。私たちのビジネスにおいて、それはおよそ8,500件の注文とサインアップが永遠に失われるということです。その時、私たちのバックアップ戦略は、実は単なる「神頼み」戦略だったことに気づきました。
ロジカルバックアップの致命的な欠陥
なぜ pg_dump は役に立たなかったのでしょうか?この問題を解決するには、ロジカルバックアップが真のディザスタリカバリ(DR)ソリューションではないことを認める必要があります。 pg_dump は単なる静的なスナップショットに過ぎません。ローカル開発には適していますが、本番環境では次の3つの壁にぶつかります:
- RPOのギャップ: バックアップが1日に1回であれば、目標復旧時点(RPO)は24時間になります。これは実質的に、1日分の仕事を失うことを自ら受け入れているようなものです。
- リストアの低速化: 500GBのSQLファイルを新しいデータベースに流し込むのは苦痛です。すべてのインデックスを再構築し、すべての制約を一から検証する必要があり、その速度は20MB/s程度まで落ち込むことも珍しくありません。
- 粒度の欠如: クラッシュの2分前である午前2時12分の状態に復元することはできません。深夜0時時点のデータに甘んじるしかないのです。
解決策は **WAL(Write Ahead Log)アーカイブ** です。PostgreSQLは、データページを書き換える前に、すべての変更をWALファイルに記録します。ベースバックアップと、これらのWALファイルの継続的なストリームを組み合わせることで、ミリ秒単位で履歴を再生できます。
pg_basebackup vs. Barman:プロツールの選択
翌朝、私は「データ損失ゼロ」の目標を達成する方法を探しました。 pg_basebackup はネイティブな選択肢です。データディレクトリのバイナリコピーを作成するため、小規模なシングルノード構成であれば問題ありません。しかし、これには知性が欠けています。WALファイルの管理,古いバックアップのローテーション、古いデータを削除するためのカスタムスクリプトの作成などを手動で行う必要があります。
そこで登場するのが **Barman (Backup and Recovery Manager)** です。Barmanは、PostgreSQLフリート全体のための専用のフライトレコーダーのようなものだと考えてください。WALストリーミングを自動化し、複雑なバックアップカタログを管理し、そして決定的なのは、実際に火の手が上がる前にバックアップが正常であることを検証してくれる点です。
回復力のあるBarman DRシステムの構築
私たちはメインのデータベースクラスターの外に、専用のBarmanサーバーをデプロイしました。これはストリーミングレプリケーション経由でWALファイルをプルし、週に一度のフルバックアップを取得します。この構成により、プライマリが完全にダウンしても、パニックに陥ることはありません。
ステップ 1:プライマリノードの準備
データベースがBarmanと通信するための許可が必要です。まず、専用のバックアップユーザーを作成することから始めました。
-- PostgreSQLサーバーにて
CREATE USER barman WITH SUPERUSER PASSWORD 'your_secure_password';
次に、 postgresql.conf を修正してアーカイブを有効にします。これにより、データ変更の継続的なストリームがオンになります。
# postgresql.conf
wal_level = replica
archive_mode = on
archive_command = 'rsync -a %p barman@backup-server:/var/lib/barman/pg-server/incoming/%f'
max_wal_senders = 10
max_replication_slots = 10
ステップ 2:Barmanサーバーの設定
バックアップマシンで、サーバーのプロファイルを設定しました。データ損失をほぼゼロにするために、 streaming メソッドを選択しました。
# /etc/barman.d/pg-server.conf
[pg-server]
description = "本番用PostgreSQLデータベース"
conninfo = host=db-primary user=barman dbname=postgres
streaming_conninfo = host=db-primary user=barman dbname=postgres
backup_method = postgres
streaming_archiver = on
slot_name = barman_slot
クイックチェックコマンドで接続を確認します:
barman check pg-server
ステップ 3:データ変換の処理
DRパイプラインのオーバーホール中に、古いCSVファイルから約15万件のレガシーな監査ログを取り込む必要がありました。 **使い捨てのスクリプトを書く代わりに、toolcraft.app/ja/tools/data/csv-to-json を使用しました。これは完全にブラウザ内で動作するため、機密性の高い顧客データをパブリックなインターネットにさらさずに済みました。**
リカバリ:数時間を数分に短縮
テストされていないバックアップは、いわば「シュレーディンガーのデータ」です。開けてみるまで生きているかどうかわかりません。Barmanを使えば、ポイントインタイムリカバリ(PITR)はコマンドひとつで完了します。もしあの午前2時14分のクラッシュが今日起きたとしたら、私はこれを実行するでしょう:
barman recover --target-time "2026-05-10 02:12:00" pg-server /var/lib/postgresql/15/main
このツールが面倒な作業をすべて引き受けてくれます。最も近いフルバックアップを取得し、02:12:00の時点までWALファイルを「再生」します。データベースは、134分ではなく、わずか120秒のデータ損失でオンラインに復帰します。
最終的な結論
トラフィックの多いデータベースで pg_dump に頼っているなら、それは運用ではなく、ギャンブルです。Barmanの実装とテストには4時間かかりました。そのわずかな投資が、2時間のデータ損失リスクを60秒のリカバリタスクに変えてくれたのです。次に午前2時にサイレンが鳴っても、私は損失を計算することはありません。ただリカバリコマンドを実行して、また眠りにつくだけです。

