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`で待たされてるな」と推測できるだけで、障害対応のスピードは段違いになる。
データベースエンジニアとして、時々こうやって「エンジンルーム」を覗いてみる癖をつけておこう。何か面白い挙動を見つけたら、また一緒に議論しようぜ。
それじゃ、今日はこの辺で。良いハッキングを!
コメント