データベースが「死んだ」とき、PostgreSQLはどうやって蘇るのか?――REDOリカバリの舞台裏
やあ。今日も元気にクエリ叩いてる?
データベースエンジニアをやっていると、避けては通れないのが「突然のクラッシュ」だよね。停電、OSのパニック、あるいはハードウェアの故障。サーバーがガクンと落ちて、再起動した瞬間のあの冷や汗が出るような静寂……。
でも、PostgreSQLはそんなことではへこたれない。再起動した瞬間、裏側では「REDOリカバリ」という、極めて堅実で美しいプロセスが走り出すんだ。今日は、このPostgreSQLの「生還の儀式」について、少し深掘りしてみようか。
—
「何が起きたか」を記した航海日誌:WAL
REDOリカバリを理解する鍵は、WAL (Write Ahead Logging) にある。
PostgreSQLは、データを更新するときに、いきなりメインのデータファイル(テーブルファイルとか)を書き換えることはしない。そんなことをしたら、書き込みの途中でクラッシュした時にデータが壊れちゃうからね。
その代わりに、「何を変えようとしているか」という変更履歴を、まずはWALというログファイルにシーケンシャル(順番)に書き出す。 これが「Write Ahead(書き込みに先立つ)」の名の由来だ。
REDOリカバリのアルゴリズム:過去から未来へ
じゃあ、いざクラッシュして再起動したとき、Postgresは具体的に何をしているのか。大きく分けると、以下の3ステップだ。
1. Redo Start Pointの特定: 最後にチェックポイント(データファイルとメモリ上の状態を同期させた地点)が記録された場所を探す。
2. WALの再送(REDO): チェックポイント以降にWALに書き込まれた変更を、最初から最後まで順番に追っていく。
3. 状態の確定: 最後に、未完了だったトランザクションをロールバックして、整合性を完璧に整える。
この「REDO」のプロセスは、いわば「歴史の再現」だよ。壊れる直前までの世界を、WALという台本を使って一瞬でシミュレートし直すわけだ。
実践的な視点:なぜこれが「速い」のか?
現場でよく「リカバリって時間かかるの?」と聞かれるんだけど、PostgreSQLのREDOは驚くほど効率的だ。
なぜなら、WALへの書き込みは「追加のみ」のシーケンシャルI/Oだから。 巨大なデータファイルをランダムに読み書きするのとはわけが違う。エンジニアとして覚えておいてほしいのは、WALの書き込み性能を上げることが、そのままデータベースの堅牢性とリカバリ速度に直結するということ。WALを置くディスクを高速なSSD(NVMeなど)に逃がすのは、単なるチューニングじゃなくて、立派な運用上の生存戦略なんだ。
コードで覗くリカバリの意志
PostgreSQLのソースコードを覗くと、`xlog.c` あたりにリカバリの核心部分がある。概念的にはこんな感じの処理が走っていると思えばいい。
/ 疑似コードで見るREDOのイメージ /
void StartupXLOG() {
// 1. 最後のチェックポイントを読み込む
XLogRecPtr checkpoint_loc = FindLastCheckpoint();
// 2. そこから最新のWALまで、ひたすら適用する
XLogRecPtr current_loc = checkpoint_loc;
while (current_loc < end_of_wal) {
XLogRecord record = ReadRecord(current_loc);
// REDO関数を呼び出して、各ページの変更を再現する
ApplyRecord(record);
current_loc = NextRecord(current_loc);
}
// 3. 整合性が取れたら、DBをオープンする
OpenDatabase();
}
この `ApplyRecord` が、まさに「過去の変更を今のファイルに適用する」というREDOの心臓部だ。シンプルだけど、この繰り返しの積み重ねがデータの整合性を守っている。
---
先輩からのアドバイス:リカバリを「信じる」ために
最後に一つ、現場の肌感覚として伝えておきたいことがある。
リカバリは「魔法」じゃない。もしWALファイルが破損していたら、どんなに優れたPostgreSQLでも完全な復旧はできない。だからこそ、定期的なバックアップと、WALのアーカイブ(アーカイブログ)の設計が不可欠なんだ。
「Postgresならリカバリしてくれるっしょ」と高を括るんじゃなくて、「いざという時、WALが手元にちゃんと揃っているか」を常に意識する。それが、プロのデータベースエンジニアとしての矜持だと思うよ。
もし君が今、運用で悩んでいるなら、まずは `pg_waldump` コマンドでWALの中身を覗いてみてほしい。あそこに刻まれているのは、データベースが必死に生き残ろうとした記録だ。それが見えたとき、きっとPostgreSQLがもっと頼もしい相棒に見えてくるはずさ。
さて、今日はこの辺にしておこうか。また何か詰まったら、いつでも聞きに来なよ。
コメント