【テクニカル・上級編】 LSN(ログシーケンス番号) – PostgreSQL

データベースの「時間」を追跡する:LSN(Log Sequence Number)という概念の深淵

PostgreSQLを長年触っていると、ふとした瞬間に「今のDBの状態は、正確にどこまで進んでいるのか?」という問いに突き当たることがあります。VACUUMの進捗、レプリケーションのラグ、あるいはクラッシュリカバリの深層――。これらすべてを貫く背骨のような存在、それがLSN(Log Sequence Number)です。

今日は、この64ビットの識別子が、いかにしてPostgreSQLという巨大な機械の「整合性」を担保しているのか、内部構造の視点から少し深く掘り下げてみたいと思います。

—

LSNは「WAL上のタイムスタンプ」である

LSNは単なるカウンタではありません。WAL(Write Ahead Log)内におけるバイト単位のオフセット値です。`0/16B3C88` のような形式で見慣れている方も多いでしょう。この前半の「0」はログセグメントのファイル番号、後半の「16B3C88」はファイル内のオフセットを指しています。

なぜこれが重要なのか。それは、PostgreSQLが「データページ」と「WAL」という二つの異なる場所にデータを書き込むという構造に起因します。

  • データページ(Shared Buffers): メモリ上の更新を非同期にディスクへフラッシュする。
  • WAL(Write Ahead Log): 更新履歴を逐次シーケンシャルに書き込む。

この非同期な関係の中で、「データページがどの時点までの更新を取り込んだか」を証明するために、各ページには `pd_lsn` というフィールドが埋め込まれています。これがあるからこそ、OSのクラッシュや電源断という最悪の事態においても、PostgreSQLは「このページはまだWALのここまでの内容しか適用されていないから、リカバリで続きを当てなきゃいけないな」と判断できるわけです。

「ページがLSNを追い越す」ことの恐怖

トラブルシューティングの現場で、ときどき遭遇するのが「LSNの不整合」に関連するエラーです。

もし万が一、WALの書き込みが完了する前にデータページがディスクに書き出されてしまったらどうなるでしょうか? 次の起動時、PostgreSQLはデータページを見て「更新済み」と判断しますが、それを証明するWALが残っていない。結果、リカバリは不可能になり、データベースは物理的な破損(Corrupted)という致命的な結末を迎えます。

これを防いでいるのが、`XLogFlush` という仕組みです。バックエンドプロセスは、データページをバッファから書き出す際、そのページが持つLSNがWAL側で確実に永続化されていることを確認(`Flush`)してからでなければ、ディスクI/Oを発行できません。この「Write-Ahead(先行書き込み)」の哲学こそが、PostgreSQLの信頼性の源泉です。

パフォーマンスチューニング:LSNがボトルネックになるとき

大規模なトランザクションをさばくシステムでは、このLSNの確認作業がパフォーマンスの足枷になることがあります。

特に、`synchronous_commit` をオンにしている場合、トランザクションのコミットは「WALがディスクに書き込まれた(Flushされた)というLSNの確認」を待機します。ここでディスクI/Oのレイテンシが跳ね上がると、TPSは一気に低下します。

よくある勘違いとして、「ディスクの書き込み速度さえ上げれば解決する」というものがありますが、アーキテクチャ的に重要なのは、「WALの書き込み頻度と、LSNの進む速度をどう制御するか」です。

  • fsyncのオーバーヘッド: 多くの書き込みが、小さなLSNの更新を繰り返すと、カーネルのfsync呼び出しでCPUが飽和します。`commit_delay` や `commit_siblings` を調整し、複数のコミットを一つのWALフラッシュにまとめる(グループコミット)ことは、高負荷時の基本戦略です。
  • レプリケーションラグ: レプリカ側が受け取ったLSNを `pg_stat_replication` で確認し、マスタとの差分(Write LSN vs Replay LSN)を監視するのは、DBAの日常です。もしここでReplay LSNが停滞しているなら、それはWALの適用(Redo処理)がボトルネックになっている証拠であり、単にネットワーク帯域を増やすだけでは解決しません。

最後に:LSNと向き合うということ

LSNは、PostgreSQLが歩んできた歴史そのものです。

私たちがクエリを発行するたび、内部ではこの64ビットの数字が静かに、しかし確実に刻まれています。トラブルシュートの際、`pg_walinspect` などのツールを使ってWALの中身を覗き込むと、LSNが指し示す先のトランザクションがまるで走馬灯のように見えてくる――。そんな感覚を覚えるようになれば、あなたも立派なPostgreSQLの「深層」に触れるエンジニアと言えるでしょう。

「今、何が起きているのか?」に迷ったときは、常にLSNを確認してください。それが、PostgreSQLという複雑な迷宮を解き明かすための、唯一無二の羅針盤なのですから。

—

今日の技術解説はここまで。皆さんの環境で「LSNの追いかけっこ」に疲れたら、一度 `checkpoint_segments` や `max_wal_size` を見直してみるのも良いかもしれません。また次回の記事でお会いしましょう。

コメント

タイトルとURLをコピーしました