フルページライト(FPI):PostgreSQLの「最後の砦」と、その代償について
PostgreSQLのアーキテクチャを語る上で、避けて通れないのがフルページライト(Full Page Writes: FPI)の存在です。
普段、我々は「PostgreSQLは堅牢だ」と口にします。しかし、その堅牢性を支えているのは、単なる理論上のACID特性だけではありません。OSやハードウェアレベルの「不完全な書き込み」という現実に対する、非常に泥臭く、そして極めて理にかなった防衛策こそが、このFPIなのです。
今日は、なぜこの機能が不可欠なのか、そして現場でパフォーマンスをチューニングする際に、我々がどのようなトレードオフと向き合わなければならないのかを深掘りしてみましょう。
なぜ、「ページ全体」なのか
データベースの最小管理単位である「ページ(デフォルト8KB)」と、ストレージ(OSやディスク)の「ブロックサイズ(通常4KB)」の乖離。これがFPIを生んだ根本原因です。
PostgreSQLがチェックポイントを実行した直後、あるページが最初に更新される際、PostgreSQLはそのページ全体をWAL(Write Ahead Log)に書き出します。これがFPIです。
「なぜ差分(delta)だけ記録しないのか?」と問われることがありますが、答えはシンプルで、「書き込みの途中でOSやディスクがクラッシュした際、ページが破損(Partial Write)するから」です。
もしOSが8KBの書き込みを2回に分けて実行している最中に電源が落ちたら? ページの前半は新しく、後半は古いという、整合性のとれない「フランケンシュタイン状態」のデータが出来上がります。この状態になったページは、WALの差分ログをリプレイしても復旧できません。だからこそ、PostgreSQLは「そのページが壊れたとしても、安全な状態に戻せるように、更新前の丸ごとバックアップをWALに持っておく」という決断を下したわけです。
現場で直面する「WALの肥大化」という影
FPIはデータベースの信頼性を担保する守護神ですが、同時にパフォーマンスにおける「コスト」でもあります。
特に、`checkpoint_segments`(現在は `max_wal_size`)が適切に設定されていない環境で、大量の更新が発生するとどうなるか。FPIがWALを猛烈な勢いで埋め尽くし、WALの生成量が激増します。これが引き起こす連鎖反応は、現場のエンジニアなら誰しも一度は経験があるはずです。
- チェックポイントの頻発: WALが急速に埋まり、チェックポイントのサイクルが短くなる。
- I/O負荷の増大: チェックポイント時のフラッシュによるディスクI/Oのスパイク。
- レプリケーションの遅延: スタンバイ側に転送すべきWALの量が増え、ネットワークやリカバリ処理のボトルネックになる。
トラブルシューティング:FPIとどう付き合うか
「FPIが重いから無効化したい」という相談を受けることがありますが、結論から言えば、それは「飛行機の安全装置が邪魔だから外したい」と言っているのと同じです。例外を除き、`full_page_writes = off` を推奨することは絶対にありません。
代わりに、我々がとるべき戦略は以下の通りです。
1. `data_checksums` の有無を確認する
もし初期化時に `data_checksums` を有効にしていれば、ページ破損の検出は可能です。しかし、FPI自体は破損を防ぐためのものであり、検出するためのものではありません。この二つは役割が異なります。
2. ファイルシステムの「原子性」を信じる
ZFSやXFSなどの堅牢なファイルシステムを使い、適切なマウントオプション(あるいはハードウェア側での電源保護機能など)がある場合、FPIによるリスクは低減できます。しかし、これらは「OSレベル」の信頼性であり、PostgreSQLのアーキテクチャが前提とする「論理的な堅牢性」とは別次元の話であることを忘れてはいけません。
3. WALの書き込みをボトルネックから解放する
もしFPIによるWALの肥大化がパフォーマンスを圧迫しているなら、WALを置くストレージを高速化する(NVMe SSDへの移行など)か、あるいは `checkpoint_completion_target` を調整して、チェックポイントの負荷を平準化し、FPIが発生するタイミングを制御するのが定石です。
最後に:エンジニアとしての矜持
FPIは、データベースという「極めて不安定なハードウェアの上に乗る、極めて不安定なOS」という土壌において、データの整合性を守り抜くための、まさに職人芸的な仕組みです。
我々エンジニアがやるべきことは、この仕組みを悪者扱いして排除することではありません。その背後にある「なぜ?」を理解し、ハードウェアの特性に合わせて適切にチューニングを施すことです。
もし皆さんの環境でWALの生成量が異常だと感じたら、まずは `pg_stat_bgwriter` を眺め、チェックポイントが意図した間隔で走っているかを確認してみてください。データベースが懸命に「守り」に徹しているその姿が、ログの中に隠れているはずですから。
それでは、また次回の技術探訪でお会いしましょう。
コメント