「やらかした!」その瞬間に戻る:PostgreSQLのリカバリターゲットを極める
データベースエンジニアとして長く現場にいると、必ず一度は冷や汗をかく瞬間が訪れます。「あ、今実行したUPDATE文、WHERE句を忘れて全行書き換えてしまった……」。
そんな絶望的な状況を救ってくれるのが、PostgreSQLのPITR(Point-in-Time Recovery)です。ただ、PITRは「いつまで戻すか」の設定を間違えると、また別の悲劇を生むことになります。
今回は、このリカバリターゲットの設定に焦点を当てて、現場で「本当に使える」知識をシェアしたいと思います。
—
リカバリターゲットって何?
PostgreSQLでベースバックアップからデータを復元する際、WAL(Write Ahead Log)を再生して「どの地点で止めるか」を指定する仕組みです。
主に `recovery.signal`(PostgreSQL 12以降)を配置したデータディレクトリ配下の `postgresql.conf`(または `recovery.conf` の後継設定)で指定します。
よく使う「ターゲット」の指定方法
基本となるのは、`recovery_target` 関連の設定です。これらを使いこなすのがリカバリの第一歩です。
1. タイムスタンプ指定 (`recovery_target_time`)
- 「2023-10-27 15:30:00 JST」のように時刻で指定します。一番直感的ですが、アプリのログとDBのタイムスタンプのズレには注意が必要です。
2. トランザクションID指定 (`recovery_target_xid`)
- 特定のトランザクションまで戻せます。「あのDELETE文の直前まで」というピンポイントな復旧に非常に強力です。
3. LSN(Log Sequence Number)指定 (`recovery_target_lsn`)
- WALの物理的な位置を指定します。精度は最強ですが、ログ解析が必要なので、相当な緊急時用ですね。
—
実践:具体的なリカバリの現場から
例えば、「誤ったバッチ処理が走り始めた直前」に戻したい場合、`recovery.signal` を配置した上で、以下のように設定するのが定石です。
postgresql.conf への追記例
restore_command = ‘cp /mnt/server/archived_wals/%f %p’
recovery_target_time = ‘2023-10-27 15:29:59 JST’
recovery_target_action = ‘pause’
なぜ `recovery_target_action = ‘pause’` が重要なのか?
ここが今回の最大の教訓です。多くの初心者は `recovery_target_action = ‘promote’`(即座に復旧完了してDBを起動)を使いがちですが、僕は必ず `pause` を推奨します。
理由を説明しましょう。指定した時刻が本当に「データが壊れる前」だったか、確信が持てますか?
1. `pause` を使うと、ターゲット地点でデータベースが停止(一時停止)します。
2. その状態でDBに接続し、`SELECT` 文を叩いて「データが壊れる前かどうか」を自分の目で確認できます。
3. もし「あ、あと30秒戻すべきだった」となれば、設定を書き換えて再度リカバリを続行できます。
この「確認のワンクッション」を挟むだけで、リカバリの失敗リスクは劇的に下がります。
—
現場のエンジニアへのアドバイス
最後に、僕がトラブル対応のたびに心がけていることを2つだけ伝えます。
- 「ターゲットの確認」を自動化しておく
`pg_waldump` というツールを使って、リカバリ前にWALファイルの内容を覗く癖をつけてください。どのトランザクションIDがいつ発行されたか、事前に把握しているだけで復旧スピードが段違いになります。
- 本番環境で一度は「練習」する
「本番と同じ手順」を、別の検証環境で最低でも一度は通しておいてください。リカバリ設定の微妙な書き方ミスや、アーカイブWALのアクセス権限エラーは、本番の緊急時にはパニックの原因になります。
まとめ
リカバリターゲットは、単なる「設定項目」ではなく、「ミスをした時の安全ネット」です。
`recovery_target_action = ‘pause’` で一度立ち止まり、本当に正しい状態かを確認する。この慎重さこそが、世界最高峰のデータベースエンジニアへの近道だと僕は信じています。
皆さんのデータベースに、穏やかな運用が訪れますように。それでは、また。
コメント