PostgreSQLの「Lock Manager」を知らずして、パフォーマンスチューニングは語れない。
やあ。今日もPostgreSQLと格闘しているかな?
現場でよく「なんかクエリが重いな」とか「デッドロックで怒られた」なんて話を聞くたびに、僕はいつも心の中で「Lock Manager、お前また仕事してるな?」と呟いているんだ。
PostgreSQLのアーキテクチャを理解する上で、Lock Managerは避けて通れない「心臓部」の一つ。今日は、教科書的な定義じゃなくて、現場のエンジニアとして「これを知っておくと世界が変わるよ」という視点で解説してみるよ。
—
1. Lock Managerって結局何者?
簡単に言えば、「共有メモリ上にある、巨大な交通整理の掲示板」だと思ってほしい。
PostgreSQLはマルチプロセスアーキテクチャだよね。複数のバックエンドプロセスが同時に同じデータに触ろうとしたとき、誰かが書き込んでいる最中に別の誰かが値を読み書きしたら……そう、データは壊滅する。
そこで登場するのがLock Managerだ。
- 場所: 共有メモリ(Shared Memory)上。
- 構造: ハッシュテーブル。
- 役割: 今誰がどのデータ(テーブル、行、インデックスなど)に対して、どんな権限(共有ロック、排他ロックなど)を持っているかを管理する。
各バックエンドプロセスは、何か操作をする前に「この行、触っていい?」とLock Managerに問い合わせる。許可が下りれば作業開始、ダメなら「お、今先客がいるな」と待機(スリープ)に入るわけだ。
—
2. 実務で知っておくべき「重い」挙動
Lock Managerは非常に高速に設計されているけれど、万能じゃない。現場でハマりやすいポイントを2つ紹介するよ。
① ロックの粒度と「行レベル」の罠
PostgreSQLは行レベルロック(Row-level lock)が優秀で、行単位で細かく制御できる。でも、例えば `ALTER TABLE` や `TRUNCATE`、あるいは特定のインデックス操作などは、テーブル全体をロック(AccessExclusiveLock)してしまうことがある。
ここが重要なんだけど、AccessExclusiveLockは「他のすべてのロックと競合する」んだ。つまり、このロックが走っている間、そのテーブルへのSELECTすら待たされることになる。Webアプリのフロントエンドでタイムアウトが多発する原因のトップランナーだね。
② ロックの「待ち行列」が長すぎるとき
あまりに多くのプロセスが同じ行を狙い続けると、Lock Managerのハッシュテーブルへのアクセス自体がボトルネックになることがある。これを「ロック競合」と呼ぶんだけど、解決策はクエリのチューニングだけじゃない。
設計レベルで「更新頻度が高すぎる行」を一つのテーブルに集めすぎない、といったアプローチが必要になることもあるんだ。
—
3. 現場で役立つ確認コマンド
「今、何が起きているか?」を知るために、僕らが毎日叩いているSQLがこれだ。
— 現在ロック待ちが発生しているプロセスを可視化する
SELECT
pid,
locktype,
mode,
granted,
relname
FROM pg_locks l
LEFT JOIN pg_class c ON l.relation = c.oid
WHERE NOT granted;
`granted` が `false` になっている行があれば、それが「今、ロックを欲しがっているけど待たされているプロセス」だ。もしこれを見つけたら、`pg_stat_activity` と組み合わせて、どのSQLが犯人なのかを特定する。これがトラブルシュートの基本ルーチンだね。
—
4. 先輩からのアドバイス:デッドロックを恐れるな
たまに「デッドロックを100%回避する設計にしたい」と相談されることがあるんだけど、正直に言うと、それはあまり現実的じゃない。
PostgreSQLには非常に賢いデッドロック検出機能がある。デッドロックが発生すると、検知プロセスが「お前ら、ループしてるぞ!」と片方を強制的にロールバックさせてくれる。
大事なのは「デッドロックを一切起こさないこと」ではなく、「デッドロックが発生したときに、適切にリトライする仕組みをアプリケーション側で作っておくこと」だ。
具体的には、トランザクションの失敗を検知したら、指数バックオフ(少しずつ待機時間を延ばしながら再試行する)を挟んで再実行する。これだけで、システムの堅牢性は劇的に上がるよ。
—
最後に:データベースと仲良くなるために
Lock Managerは決して「邪魔なもの」じゃない。あなたのデータを破損から守り、整合性を担保してくれる、最も忠実なガードマンだ。
もし今度クエリが遅くてイライラしたら、「ああ、今Lock Managerが一生懸命調整してくれてるんだな。競合が起きないように設計を見直すチャンスだな」と一歩引いて考えてみてほしい。
そうやってデータベースの視点に立つことが、一流のエンジニアへの近道だと僕は思うよ。
さて、今日はこの辺で。また何か気になったら気軽に聞いてくれ。次は `MVCC` とロックの深い関係について話そうか。あれも面白いテーマだよ。
コメント