なぜPostgreSQLは「ページ全体」を書き出すのか?「フルページライト」の真実
「PostgreSQL、たまに書き込みが重くなるんだよね……」
現場でそんな悩みを聞くたびに、僕はまず「フルページライト(Full Page Writes, FPW)」のことを思い浮かべるんだ。
正直、教科書を見ると「チェックポイント後の初回変更時にページ全体をWALに書き出す」なんて書いてあるよね。でも、これって直感的に考えると、すごく非効率じゃない?「なんでわざわざ、たった数バイトの更新のために8KBものデータを書き出さなきゃいけないんだ?」って思うよね。
今日は、そんな疑問を持つ君のために、この「フルページライト」という、一見無駄に見えて実は命綱のような仕組みの正体を紐解いていこう。
—
なぜ「差分」だけじゃダメなのか?
データ更新の基本は、本来「差分(Redoログ)」だけで十分なはずだよね。でも、PostgreSQLには逃げられない物理的な制約がある。それが「OSのページサイズとデータベースのページサイズの不一致」だ。
- PostgreSQLのページサイズ:通常 8KB
- OSのファイルシステムのページサイズ:通常 4KB
ここで、PostgreSQLが8KBのページを書き込んでいる最中にOSやハードウェアがクラッシュしたとする。すると何が起きる? 「前半の4KBは書き込めたけど、後半の4KBは書き込めなかった」という「部分的な書き込み(Partial Write)」が発生するんだ。
データベースのファイルが一部だけ壊れた状態。これはもう、通常のRedoログ(差分情報)だけでは絶対に修復できない。なぜなら、Redoログは「そのページが正常であること」を前提に適用されるものだからね。
そこで登場するのが「フルページライト」だ。
—
フルページライトがやっていること
チェックポイントが終わった直後の「最初の更新」が発生したとき、PostgreSQLは泣く泣く(?)そのページ全体をWAL(Write Ahead Log)に書き出す。
仕組みは至ってシンプルだ。
1. チェックポイント発生: ダーティページがディスクにフラッシュされる。
2. フラグのクリア: そのページに対する「フルページ書き出し済み」フラグがリセットされる。
3. 最初の変更: `UPDATE`文などが来ると、PostgreSQLは「おっと、まだこのページはログに取ってないな」と判断する。
4. 全書き出し: 8KBのページデータまるごとをWALに書き込む。
5. フラグのセット: 以降、次のチェックポイントまで、そのページに対するフルページ書き出しはスキップされる。
つまり、「クラッシュからの復旧時に、もしページが壊れていても、フルページライトさえあればそのページを『過去の状態』からやり直せる」というわけ。まさに最強の保険だね。
—
現場でのチューニング:いつ意識すべきか?
この機能、オフにする設定(`full_page_writes = off`)もあるけれど、絶対にオフにしちゃダメだ。 本番環境でこれをオフにするのは、シートベルトを外してF1カーを運転するようなもの。
ただし、パフォーマンスを気にする君が意識すべきポイントはここだ。
1. `full_page_writes` と「WALの肥大化」
大量の更新処理(バッチ処理など)を走らせると、フルページライトが頻発してWALの生成量が跳ね上がる。ディスクI/Oがボトルネックになっているなら、まずはここを疑うべきだ。
2. ファイルシステムとの付き合い方
最近のLinux(ext4やxfsなど)には、`data=ordered`モードや、PostgreSQL 15以降で導入された「原子的な書き込み(atomic writes)」をサポートするハードウェアなど、OSレベルで部分書き込みを防ぐ手立てが増えてきている。それでも、僕は「フルページライトはオンのまま」を強く推奨する。安心感には代えられないからね。
—
実際に確認してみよう
今の設定がどれくらいフルページライトの影響を受けているか、気になったら以下のクエリを叩いてみてくれ。
SELECT
pg_stat_get_wal_senders() AS senders, — レプリケーション状況
stats_reset,
full_page_writes,
wal_buffers
FROM pg_stat_bgwriter;
もしWALの書き出し量があまりに多いようなら、以下の対策を検討しよう。
- チェックポイントの間隔を広げる: `max_wal_size` を大きく設定して、チェックポイントの頻度を下げる。これでフルページライトが発生する回数を減らせる。
- I/Oサブシステムの強化: 単純にディスク性能が足りていない場合が多い。NVMe SSDへの換装や、RAID構成の見直しを検討するタイミングかもしれないね。
—
先輩からのアドバイス
「フルページライト=悪」と捉えるエンジニアもいるけれど、これはPostgreSQLの信頼性を支える、非常に理にかなった「防波堤」だ。
もし君が「書き込みが遅い」というトラブルシューティングをするなら、まずは`pg_stat_bgwriter`を見て、チェックポイントが頻繁に発生していないか確認してほしい。フルページライトを減らす正攻法は、無理に機能をオフにすることではなく、チェックポイントのタイミングを最適化することにあるんだ。
データベースの奥底で何が起きているか想像できるようになると、チューニングは一気に楽しくなるよ。何か行き詰まったら、いつでも聞いてくれ。また現場で会おう。
コメント