PostgreSQLの「心臓」を覗く:WALレコードの物理構造を解剖する
やあ。今日は少し深掘りした話をしようか。
PostgreSQLを触っていると、必ず耳にするのが「WAL(Write Ahead Log)」だよね。バックアップやレプリケーションの文脈で「WALが溜まってディスクを圧迫している」とか「レプリケーションラグが…」なんて会話は日常茶飯事だ。
でも、WALが物理的にどういうデータ構造をしていて、なぜクラッシュリカバリで魔法のようにデータを復旧できるのか。その中身まで語れるエンジニアは意外と少ない。今日は、PostgreSQLの「心臓」とも言えるWALレコードの構造について、現場の視点から少し紐解いていこう。
—
WALレコードは「変更の履歴書」だ
WALレコードは、単なるテキストログじゃない。データベースが「何をしたか」という変更の断片を、極めて効率的に、かつ確実に保存するためのバイナリデータだ。
一つのWALレコードは、大きく分けて以下のパーツで構成されている。
- LSN (Log Sequence Number): これがWALの「時刻」のようなもの。8バイトの整数で、現在のWALファイル内の位置を指し示すポインタだね。
- Resource Manager ID (rmid): 「誰がこの変更をしたか」を示すID。ヒープなのか、インデックスなのか、あるいはトランザクション管理(CLOG)なのか。これによって、リカバリ時にどのコードパスでデータを再適用するかを決定する。
- Data Payload: 実際に変わった内容。これがメインディッシュだ。ページ全体を書き込むこともあれば、差分(Delta)だけを書き込むこともある。
- Checksum: データの整合性を担保する鍵。WALが壊れていないか、リカバリ時に検証するために必須のパーツだ。
なぜこの構造が重要なのか?
現場でよくあるのが、「なぜWALはこんなに肥大化するのか?」という問いだ。
実は、PostgreSQLの設定で `full_page_writes` をオンにしていると、チェックポイント直後の最初のページ書き込み時に、ページ全体(8KB分!)がWALに書き込まれる。これを「フルページイメージ」と呼ぶ。
もしデータベースのページがOSレベルで壊れていたら、差分ログだけではリカバリできないよね。だから、「たとえコストがかかっても、ページ全体を記録して確実に復旧させる」という設計思想になっているわけだ。ここを理解していないと、ストレージ容量のプランニングで痛い目を見ることになる。
—
実際にWALの中身を覗いてみる
理屈ばかりじゃつまらないだろう? 実際に自分の環境で確かめてみるのが一番早い。PostgreSQLには `pg_waldump` という最高のツールがある。
適当なトランザクションを発行した後、ターミナルでこんなふうに打ってみてほしい。
最新のWALファイルを解析するコマンド例
pg_waldump -p /var/lib/postgresql/data/pg_wal/ 000000010000000000000001
出力を見ると、こんな感じのログが流れるはずだ。
rmgr: Heap len (rec/tot): 54/ 54, tx: 602, lsn: 0/016B3D90, prev 0/016B3D68, desc: INSERT off 1, blkref #0: rel 1663/16384/16385 blk 1
- rmgr: Heap: ヒープ領域(テーブルデータ)への変更だ。
- tx: 602: トランザクションID。
- lsn: 0/016B3D90: 今まさにこのレコードが書き込まれた場所。
- desc: INSERT off 1: オフセット1の場所にデータを挿入した、という意味だね。
このログを読み解けるようになると、「今、データベースの中で何が起きているのか」が手に取るようにわかるようになる。トラブルシューティングの際、ログファイルだけでは追えない複雑な事象を切り分ける強力な武器になるはずだ。
—
実務のアドバイス:WALと付き合うために
最後に、現場の先輩として一つだけアドバイスを。
WALは「データベースの究極のバックアップ」だ。レプリケーションの同期遅延や、チェックポイントの頻度調整を行うとき、このWALレコードの構造と生成量をイメージできるかどうかで、チューニングの精度が劇的に変わる。
特に、大量の更新が走るバッチ処理の最中に `pg_waldump` でWALの生成速度を観察してみるといい。「ああ、このインデックス更新がWALを圧迫しているんだな」という感覚が、肌感覚として掴めるようになるはずだ。
データベースエンジニアとしての腕を上げる近道は、ドキュメントを読むこと以上に、こうした「内部で何が起きているか」を可視化して、納得することにあると思うよ。
もし次にレプリケーションラグで悩んだら、まずは `pg_waldump` でWALの中身を覗いてみてくれ。そこには、君が投げたSQLたちが、淡々と記録されていく姿が見えるはずだから。
それじゃ、また。現場で困ったら、いつでも聞きに来てくれ。
コメント