LOCK

Name

LOCK  -- テーブルの明示的なロック

Synopsis

LOCK [ TABLE ] name [, ...]
LOCK [ TABLE ] name [, ...] IN lockmode MODE

ここで lockmode は以下のいずれかです。

	ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE |
	SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
  

入力

name

ロックする既存のテーブルの名前です (スキーマ修飾名でも可)。

ACCESS SHARE MODE

これは最も制限の弱いロックモードです。このモードと競合するのは ACCESS EXCLUSIVE モードのみです。これは、ALTER TABLEDROP TABLE そして VACUUM FULL コマンドの同時実行によってテーブルが変更されないように保護するために使われます。

Note: SELECT コマンドは、参照されるテーブル上でこのモードのロックを獲得します。 一般に、テーブルの変更は行なわずに読み取りのみを行う問い合わせの場合は、このロックモードを獲得します。

ROW SHARE MODE

EXCLUSIVE と ACCESS EXCLUSIVE ロックモードに競合します。

Note: SELECT FOR UPDATE コマンドは、ターゲットテーブルに対してこのモードのロックを獲得します (他の、参照はされているが FOR UPDATE としては選択されていないテーブルの ACCESS SHARE ロックに加えて)。

ROW EXCLUSIVE MODE

SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVEモードに競合します。

Note: UPDATEDELETE、および INSERT の各コマンドは、ターゲットテーブルに対してこのロックモードを獲得します (その他の参照テーブル用の ACCESS SHARE ロックに加えて)。 一般に、このロックモードはテーブル内のデータを変更する問い合わせによって獲得されます。

SHARE UPDATE EXCLUSIVE MODE

SHARE UPDATE EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE モードに競合します。 このモードはスキーマの変更と VACUUM の同時実行からテーブルを保護します。

Note: (FULL なしの) VACUUM によって獲得されます。

SHARE MODE

ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE モードに競合します。 このモードは同時データ変更からテーブルを保護します。

Note: CREATE INDEX によって獲得されます。

SHARE ROW EXCLUSIVE MODE

ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE モードに競合します。

Note: PostgreSQL コマンドでは、このロックモードを自動的には獲得しません。

EXCLUSIVE MODE

ROW SHARE、ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE モードに競合します。このモードでは同時 ACCESS SHARE のみを許可します。つまりトランザクションがこのロックモードを持っていると、テーブルの読み取りのみの同時処理が許可されます。

Note: PostgreSQL コマンドでは、このロックモードを自動的には獲得しません。

ACCESS EXCLUSIVE MODE

すべてのロックモードと競合します。 このモードを使用すると、どのような場合でもこの権限を持っているトランザクションのみがテーブルにアクセスできます。

Note: ALTER TABLEDROP TABLEVACUUM FULL の各文によって獲得されます。 モードを明示的に指定していない LOCK TABLE 文では、これがデフォルトのロックモードになります。

出力

LOCK TABLE

ロックの獲得に成功しました。

ERROR name: Table does not exist.

name が存在しない場合に返されるメッセージです。

説明

LOCK TABLE はテーブルレベルのロックを獲得し、必要であれば競合するロックが解除されるのを待ちます。 ロックは、一度取得されると現行のトランザクションが完了するまで保持されます。 (UNLOCK TABLE コマンドはありません。ロックはトランザクションの終了時に常に解除されます。)

テーブルを参照するコマンドのために自動的にロックを獲得する場合、PostgreSQL は常に使用可能な一番弱いロックモードを使用します。LOCK TABLE はより制限の強いロックが必要な場合のために用意されています。

例えば、アプリケーションが隔離レベル READ COMMITTED でトランザクションを実行し、そのトランザクションの期間中テーブルのデータの安定性を確実にする必要がある場合を考えてみます。これを達成するために、 問い合わせ実行前にテーブル全体にSHAREロックモードを使用することができます。 これにより、データが同時に変更されるのを防ぎ、それ以降のテーブルの読み取りを安定させることができます。なぜなら SHARE ロックモードは書き込み側が獲得する ROW EXCLUSIVE ロックと競合するので LOCK TABLE name IN SHARE MODE 文は、ROW EXCLUSIVE の同時保持者のうち誰かがコミットまたはロールバックするのを待つからです。 このように、一度ロックを獲得すると、コミットされていない状態の書き込みはなくなり、ユーザがロックを解除するまで誰も書き込みを開始することはできません。

Note: 隔離レベル SERIALIZABLE でのトランザクション実行中にこれと同様の効果を得るには、DML 文を実行する前に LOCK TABLE 文を実行する必要があります。 シリアライザブルなトランザクション側から参照するデータの状態は、最初の DML 文が開始された時点で固定されます。 後の LOCK も同時書き込みを防ぎますが、トランザクションの読み込み対象のデータがコミットされた最新の値に対応しているかは保証されません。

このようなトランザクションでテーブル内データを変更する場合は、SHARE モードではなく SHARE ROW EXCLUSIVE ロックモードを使用する必要があります。 これによって、この種のトランザクションが同時に複数実行されることがなくなります。 SHARE ROW EXCLUSIVE を使用しないと、デッドロックが発生する可能性があります。 つまり、2 つのトランザクションの両方が SHARE モードを獲得したものの、実際に更新を行うための ROW EXCLUSIVE モードを獲得することができないような状態になる可能性があります。 (トランザクション自身のロックは競合しないので、トランザクションは SHARE モードを保持している時に ROW EXCLUSIVE を獲得することができます。しかし、他のトランザクションが SHARE モードを保持している時には ROW EXCLUSIVE を獲得することはできません。)

デッドロック状態を避けるために、2 つの一般的なルールがあります。

PostgreSQL はデッドロックを検出し、少なくても 1 つの待ち状態のトランザクションを、デッドロックを解消するためにロールバックします。 このルールに厳密に従ったアプリケーションを作成するのが実用的でない場合は、トランザクションがデッドロックによってアボートした場合に再試行するようにするという手段もあります。

複数のテーブルをロックする時、LOCK a, b; コマンドは、LOCK a; LOCK b; と同じです。テーブルは LOCK コマンドで指定された順番で、一つ一つロックされます。

注釈

LOCK ... IN ACCESS SHARE MODE には対象テーブルに対するSELECT 権限が必要です。その他の形の LOCK には全て UPDATEDELETE、またはその両方の権限が必要です。

LOCK は通常、トランザクションブロック(BEGIN...COMMIT) の内側でのみ使用されます。ロックはトランザクションの終了後すぐに削除されるからです。 トランザクションブロック外部のLOCK コマンドはそれ自体がトランザクションになりますので、ロックは入手された後すぐに削除されます。

RDBMS ロックは以下の標準用語を使います。

EXCLUSIVE

排他的ロックは、同種のほかのロックが付与されることを防ぎます。

SHARE

共有ロックは、同種のロックを他が持つことを認めます。 しかし、対応する排他的ロックが認められることを防ぎます。

ACCESS

テーブルスキーマをロックします。

ROW

各行を個別にロックします。

PostgreSQL はこの用語に厳密には従っていません。 LOCK TABLE は、テーブルレベルのロックのみを扱うので、モード名に ROW が含まれるのは適切ではありません。 これらのモード名は、ロックされたテーブル内での行レベルのロックを獲得しようとしていると、通常は解釈されてしまうでしょう。 また、ROW EXCLUSIVE モードも共有可能なテーブルロックであるため、厳密にはこの命名に従っていません。 LOCK TABLE に関しては、すべてのロックモードが同じ意味を持っていることに注意してください。違うのは、どのモードがどのモードと競合するかという規則だけです。

使用方法

外部キーテーブルへの挿入を行なう際に、プライマリキーテーブルへの SHARE ロックを獲得します。

BEGIN WORK;
LOCK TABLE films IN SHARE MODE;
SELECT id FROM films
    WHERE name = 'Star Wars:Episode I - The Phantom Menace';
-- レコードがなければ ROLLBACK して下さい。
INSERT INTO films_user_comments VALUES
    (_id_, 'GREAT!I was waiting for it for so long!');
COMMIT WORK;
   

削除操作を行なう際にプライマリキーテーブルの SHARE ROW EXCLUSIVE ロックを取得します。

BEGIN WORK;
LOCK TABLE films IN SHARE ROW EXCLUSIVE MODE;
DELETE FROM films_user_comments WHERE id IN
    (SELECT id FROM films WHERE rating < 5);
DELETE FROM films WHERE rating < 5;
COMMIT WORK;
   

互換性

SQL92

SQL92 には LOCK TABLE は ありません。 その代わりにトランザクションの同時性レベルを指定する SET TRANSACTION を使用します。PostgreSQL はこれ もサポートしています。 詳細については SET TRANSACTION を参照して下さい。

ACCESS SHARE、ACCESS EXCLUSIVE、SHARE UPDATE EXCLUSIVE ロックモードを除き、PostgreSQL のロックモードとLOCK TABLE 構文はOracle(TM) のものと互換性があります。