「あの日、あの時」に帰るための設計図:PostgreSQLのリカバリターゲットを再考する
夜中に鳴り響くアラート、真っ青になる顔、そして頭をよぎる「データ削除のコマンドを打ったのは誰だ?」という問い。DBエンジニアなら一度は(あるいは何度も)経験する悪夢です。
PostgreSQLにおけるPITR(Point-in-Time Recovery)は、そんな絶望を希望に変えるための最後の砦ですが、いざという時に「どの地点で止めるか」の解像度を高めておかないと、リカバリ作業そのものが二次災害を招きかねません。
今日は、リカバリターゲット(`recovery_target`)の設定について、マニュアルの表面的な解釈を超えた、アーキテクチャの裏側を覗いてみましょう。
ターゲット指定の「解像度」と内部的挙動
PostgreSQLがWAL(Write Ahead Log)をリプレイする際、リカバリターゲットの設定は単なる「停止スイッチ」ではありません。これは、リプレイエンジンに対する強力なフィルタリング機構です。
現在、我々が選択できる主要なターゲットは主に3つあります。
- `recovery_target_time`: タイムスタンプによる指定。運用側が把握しやすい反面、秒単位の精度では不十分な場合がある。
- `recovery_target_xid`: トランザクションIDによる指定。コミット順序が明確であり、確実性が高い。
- `recovery_target_lsn`: LSN(Log Sequence Number)による指定。物理的なログのオフセットそのもの。
熟練エンジニアなら既にお気づきでしょうが、LSN指定こそが最も低レイヤで確実なリカバリ手段です。
なぜLSNが最強なのか?
タイムスタンプはOSの時計やサーバー間の時刻同期(NTP)という「外部要因」に依存します。一方で、LSNはPostgreSQLのWALストリームにおける絶対的な物理位置です。
大規模なバッチ処理でデータが破壊された際、`pg_walinspect`(v15以降)やログの調査から「このLSNで止めるのが正解だ」と特定できれば、タイムスタンプの揺らぎに悩まされることはありません。私は障害対応時、まずログを追って該当トランザクションのLSNを特定することから始めます。それが最も手戻りのないリカバリへの近道だからです。
「リカバリの落とし穴」を回避するための設計思考
ターゲットを指定してリカバリを行う際、最も注意すべきは`recovery_target_action`の挙動です。デフォルトの`pause`を活用していますか?
recovery_target_action = ‘pause’
リカバリが終わった瞬間にDBが稼働してしまうと、誤ったデータを含んだ状態でアプリケーションが接続し、さらなる惨事を招く可能性があります。特に運用現場では、「リカバリが終わったら一度止めて、整合性を検証する」というプロセスを組み込むべきです。
パフォーマンスという観点からの警告
リカバリターゲットを設定すると、PostgreSQLはWALをリプレイしながら、「ターゲットに到達したか?」を都度チェックします。
- チェックポイントの密度: 巨大なWALをリプレイする場合、チェックポイントの頻度がリカバリ速度に直結します。
- インデックスの再構築: リカバリ完了時にインデックスの整合性を確認するためのIO負荷は無視できません。
もしリカバリターゲットがWALの終盤にある場合、リプレイ自体は高速でも、その後のオープン時のチェック処理で数十分待たされることがあります。この「最後の一押し」の時間を甘く見ると、障害復旧のSLAを突き抜けることになります。
最後に:エンジニアとして持つべき視点
リカバリターゲットの設定は、単なる設定ファイルへの追記作業ではありません。それは「システムの歴史のどこを切り出すか」という、データベースの構造を深く理解している者だけが許される彫刻のような作業です。
もしあなたが今、運用設計を見直しているなら、以下のことを自問してみてください。
1. 「障害発生時、どのツールを使ってターゲットLSNを即座に特定できるか?」
2. 「リカバリ後の検証用環境で、安全にターゲット到達を確認できるフローがあるか?」
PostgreSQLは非常に堅牢なエンジンですが、リカバリの精度は、そのエンジンの特性をどれだけ愛し、理解しているかという「エンジニアの技量」に大きく依存します。
次にリカバリターゲットの設定が必要になったとき、マニュアルではなく、WALが刻んできた「歴史の断片」を眺めるような気持ちでコマンドを叩いてみてください。きっと、これまでとは違う景色が見えるはずです。
コメント