lock manager

src/backend/storage/lmgr/READMEより:

LOCKING OVERVIEW

PostgreSQLは,以下の3種類のロックを使用する。

  • Spinlocks

Spinlockは超短期的なロックを取得することを意図しており,主にLightweight lockのインフラとして使用される。
Spinlockが要求されると,ロックが取得できるまでbusy loopを回してロック取得を試みる。ハードウェアがTAS(Test And Set命令)を提供している場合,ロックの取得はこれ(TAS命令)を使って実装される。
約1分間ロックが取得できない場合(これは無限に長い時間と考えていい),タイムアウトになる。
Spinlockはデッドロックの検出やエラー発生時の自動開放などの機能は提供しない。

  • Lightweight locks(LWLocks)

LWLockは,主に共有メモリにあるデータにアクセスするときに使用され,排他ロックと共有ロックの2種類のモードをサポートしている。
デッドロックを検出する仕組みは無い。エラー発生時にロックを自動的に開放するため,LWLockの保持中にエラーが発生しても安全である。
競合するロックが存在しないとき,ロックの確保と開放はとても速い。
プロセスがロックを待たなければならないときは,CPUリソースを消費しないように,セマフォによって待機する。ロック待ちのプロセスへは,到着順にロックが与えられる。(現在の実装では,到着順にならないこともある)
LWLockにはタイムアウトが存在しない。

  • Regular locks(heavyweight locks)

Regular lockは,主にテーブルやブロックをロックするために使用される。
Regular lockは様々なロックモードをサポートしており,デッドロックの検出やトランザクション終了時の自動開放を提供する。


Spin locksやLWLocksの獲得は、これらのロックがリリースされるまでqueryのキャンセルやdie()による中断を受け付けない原因となる。この制限はRegular locksにはない。つまりReqular lockを待機中に、queryのキャンセルやdie()による割り込みを受け入れることができることに注意すること。しかしSpin lockやLWLockを待機中は、これらは受け入れられない。したがって待機時間が2, 3秒を超えるかもしれない場合、LW locksを使うことは良い考えではない。