無料スクリプト配布のPHP.TO   PHPの実用的なtips PHPマニュアル MySQLマニュアル Apacheマニュアル PostgreSQLマニュアル マニュアル検索    

LOCK

名前

LOCK -- テーブルをロックする

概要

LOCK [ TABLE ] [ ONLY ] 

name

 [ * ] [, ...] [ IN 

lockmode

 MODE ] [ NOWAIT ]





lockmode

には以下のいずれかが入ります。



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

説明

LOCK TABLE はテーブルレベルのロックを取得します。必要であれば競合するロックが解除されるまで待機します。 NOWAIT が指定された場合は、対象のロックを取得できなくても待機しません。 この場合、すぐにロックが取得できなければ、このコマンドを中止し、エラーを出力します。 ロックは、一度取得されると現行のトランザクションが完了するまで保持されます ( UNLOCK TABLE といったコマンドはありません。 ロックが解除されるのは常にトランザクションの終了時です)。

テーブルを参照するコマンドのために自動的にロックを取得する場合、 PostgreSQL は常に使用可能な一番弱いロックモードを使用します。 LOCK TABLE はより制限の強いロックが必要な場合のために用意されています。 例えば、隔離レベルREAD COMMITTEDでトランザクションを実行するアプリケーションで、トランザクションの間中、テーブルのデータを確実に安定させる必要がある場合を考えます。 この場合、問い合わせ実行前にテーブル全体に SHARE ロックモードを使用します。 これにより、データが同時に変更されるのを防ぎ、それ以降のテーブルの読み取りを安定させることができます。 なぜなら SHARE ロックモードは書き込み側が取得する ROW EXCLUSIVE ロックと競合するので、 LOCK TABLE name IN SHARE MODE 文は、 ROW EXCLUSIVE を保持しているトランザクションがコミットまたはロールバックされるのを待つからです。 したがって、一度ロックを取得してしまえば、コミットされていない状態の書き込みは存在しないことになります。さらに、ロックを解除するまで他のアプリケーションは書き込みを開始することができません。

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

このようなトランザクションでテーブル内データを変更する場合は、 SHARE モードではなく SHARE ROW EXCLUSIVE ロックモードを使用する必要があります。 これによって、この種のトランザクションが同時に複数実行されることがなくなります。 SHARE ROW EXCLUSIVE を使用しないと、デッドロックが発生する可能性があります。 2つのトランザクションの両方が、 SHARE モードを取得していながら、実際の更新に必要な ROW EXCLUSIVE モードを取得できない状態になる可能性があるためです (トランザクション自身が所有しているロック間は競合しないので、トランザクションは SHARE モードを保持している間も ROW EXCLUSIVE を獲得することができます。 しかし、他のトランザクションが SHARE モードを保持している時には ROW EXCLUSIVE を獲得することはできません)。 デッドロックを回避するには、全てのトランザクションが、必ず同一オブジェクトに対して同一の順番でロックを取得するようにしてください。 また、1つのオブジェクトに対して複数のロックモードを呼び出す場合、トランザクションは常に最も制限の強いモードを最初に取得しなければなりません。

ロックモードとロック取得方針についてのより詳細については 項13.3 を参照してください。

パラメータ

name

ロックする既存のテーブルの名前です(スキーマ修飾名も可)。 テーブル名の前に ONLY が指定された場合、そのテーブルのみをロックします。 ONLY が指定されない場合、そのテーブルとすべての子テーブル(もしあれば)をロックします。 省略することもできますが、テーブル名の後に * を指定することで、明示的に継承するテーブルも含まれることを示すことができます。

LOCK a, b; というコマンドは LOCK TABLE a; LOCK TABLE b; と同じです。 テーブルは1つひとつ LOCK で指定された順番でロックされます。

lockmode

ロックモードには、取得するロックと競合するロックを指定します。 ロックモードについては、 項13.3 で説明します。

ロックモードを指定しない場合、最も制限が強い ACCESS EXCLUSIVE が使用されます。

NOWAIT

LOCK TABLE が競合するロックの解放まで待機しないことを指定します。 指定したロックがすぐに取得できない場合、トランザクションはアボートされます。

注釈

LOCK TABLE ... IN ACCESS SHARE MODE には、対象テーブルの SELECT 権限が必要です。 他の形式の LOCK には、テーブルレベルの UPDATE DELETE TRUNCATE 権限を持たなければなりません。

LOCK TABLE はトランザクションブロックの外側では意味がありません。 文が完了するまでしかロックは保持されません。 したがって PostgreSQL LOCK がトランザクションブロックの外側で使用された場合にエラーを報告します。 トランザクションブロックを定義するためには BEGIN および COMMIT (または ROLLBACK )を使用してください。

LOCK が扱うのはテーブルレベルのロックのみです。 そのため、モード名に ROW が含まれるのは適切ではありません。 これらのモード名によって、普通は、ロックされたテーブル内で行レベルのロックを取得できると思ってしまうでしょう。 また、 ROW EXCLUSIVE モードは共有可能なロックです。 LOCK TABLE に関しては、全てのロックモードが同じ意味を持っていることに注意してください。 違うのは、どのモードがどのモードと競合するかという規則だけです。 行レベルでのロックを獲得する方法については SELECT マニュアルページの 項13.3.2 ロック処理句 を参照してください。

外部キーテーブルへの挿入を行う際に、プライマリキーテーブルへの 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;

互換性

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

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


powered by SEO.CUG.NET