【実務・中級編】 軽量ロック(LWLock) – PostgreSQL

PostgreSQLの「心臓部」を覗く:LWLock(軽量ロック)と上手く付き合う作法

やあ。データベースの深淵へようこそ。

普段、PostgreSQLを触っていると「`Lock`」という言葉は、どうしても`SELECT FOR UPDATE`や`RowExclusiveLock`といった、SQLレベルのロックを想像しがちだよね。でも、PostgreSQLの内部、特に共有メモリ上のデータ構造を保護する「真の番人」は別にある。

それが、今回話すLWLock(Lightweight Lock)だ。

派手さはないけれど、こいつの挙動を理解しているか否かで、高負荷時のPostgreSQLの振る舞いに対する「解像度」が劇的に変わる。今日は、技術者同士の雑談のようなノリで、LWLockの正体を深掘りしていこう。

—

1. なぜ「スピンロック」じゃダメなのか?

LWLockを理解するには、まずその一つ下の階層にある「スピンロック」と比較するのが一番早い。

  • スピンロック: 非常に高速だけど、ロックが取れるまでCPUを回し続ける(ビジーウェイト)。短い処理には最適だけど、重い処理でこれを使うと、CPU使用率が跳ね上がってシステムが死ぬ。
  • LWLock: 共有メモリ上のデータ構造(バッファデスクリプタやWAL挿入ポイントなど)を守るためのもの。スピンロックより少し重いけど、競合した時に「待機キュー」に入れるという賢い機能がある。

そう、LWLockは「競合した時にスリープできる」という点が最強なんだ。これのおかげで、PostgreSQLはマルチコア環境で膨大な並列処理を捌けるようになっている。

2. LWLockの「2つの顔」:排他と共有

LWLockには、お馴染みの2つのモードがある。

1. LW_EXCLUSIVE: 「俺が書き換えるから誰も触るな」。バッファの中身を更新する時とかに使う。
2. LW_SHARED: 「読むだけならみんなでどうぞ」。ページの内容を読み取る時とかに使う。

これ、実は`pg_stat_activity`を見ていても直接は出てこない。でも、システム全体のパフォーマンスが落ちている時、`pg_stat_activity`で`wait_event_type`が`LWLock`になっているのを見たら、「あ、今こいつがメモリ上の取り合いで渋滞してるな」と直感できるようになる。これができると、一歩上のエンジニアだね。

3. 実践:LWLockをどうコードで扱うか?

もし君がPostgreSQLの拡張モジュール(C言語)を書いているなら、自前でLWLockを確保して使う場面が出てくるかもしれない。基本のパターンはこんな感じだ。

/ ロックを取得(排他モード) /
LWLockAcquire(my_custom_lock, LW_EXCLUSIVE);

/ — ここで共有メモリ上のデータに安全にアクセス — /
shared_data->value += 1;

/ ロックを解放 /
LWLockRelease(my_custom_lock);

シンプルだろう?
でも、ここで一つだけ「現場の教訓」を伝えておくよ。「ロックの保持期間は極限まで短くしろ」。

LWLockはスリープができるとはいえ、ロックを掴んだまま重いI/O処理や、無駄な計算を挟むと、その瞬間にシステム全体のボトルネックが完成する。ロックを確保する直前に必要な計算を済ませ、ロックを取ったら「データの更新のみ」を行って即座に離す。これが鉄則だ。

4. 競合が起きたらどうすべきか?

現場でよくあるのが、特定のLWLock(例えば`WALWriteLock`や`BufMappingLock`など)の競合が激しくなり、パフォーマンスが急落するケースだ。

そんな時、ログを見て「LWLockの競合だ!」と騒ぐだけでは足りない。

  • ハードウェアの限界か?: メモリ帯域やCPUコア数は足りているか。
  • クエリの効率は?: 不要なインデックスの更新がバッファの競合を招いていないか。
  • 設計の甘さか?: 共有メモリにアクセスする処理がボトルネックになっていないか。

LWLockは、言ってみれば「システムの交通整理」をしている警備員だ。警備員が忙しすぎてパンクしているなら、それは彼らのせいじゃなく、そもそも「交通量(トランザクション数や設計)」に問題がある可能性が高いんだよ。

最後に

LWLockはPostgreSQLの「静かなる主役」だ。普段の運用で直接こいつをいじることはないかもしれない。でも、`pg_stat_wait_event`を見て「あ、今`BufMappingLock`で待たされてるな」と推測できるだけで、障害対応のスピードは段違いになる。

データベースエンジニアとして、時々こうやって「エンジンルーム」を覗いてみる癖をつけておこう。何か面白い挙動を見つけたら、また一緒に議論しようぜ。

それじゃ、今日はこの辺で。良いハッキングを!

コメント

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