.\\" auto-generated by docbook2man-spec $Revision: 1.2 $
.TH "LOCK" "" "2003-08-02" "SQL - 言語" "SQL コマンド"
.SH NAME
LOCK \- テーブルの明示的なロック
.SH SYNOPSIS
.sp
.nf
LOCK [ TABLE ] \fIname\fR [, ...]
LOCK [ TABLE ] \fIname\fR [, ...] IN \fIlockmode\fR MODE

ここで \fIlockmode\fR は以下のいずれかです。

	ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE |
	SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
  
.sp
.fi
.SS "入力"
.PP
.TP
\fB\fIname\fB\fR
ロックする既存のテーブルの名前です (スキーマ修飾名でも可)。
.TP
\fBACCESS SHARE MODE\fR
これは最も制限の弱いロックモードです。このモードと競合するのは ACCESS EXCLUSIVE モードのみです。これは、\fBALTER TABLE\fR、 \fBDROP TABLE\fR そして \fBVACUUM FULL\fR コマンドの同時実行によってテーブルが変更されないように保護するために使われます。
.sp
.RS
.B "Note:"
\fBSELECT\fR コマンドは、参照されるテーブル上でこのモードのロックを獲得します。 一般に、テーブルの変更は行なわずに読み取りのみを行う問い合わせの場合は、このロックモードを獲得します。
.RE
.sp
.TP
\fBROW SHARE MODE\fR
EXCLUSIVE と ACCESS EXCLUSIVE ロックモードに競合します。
.sp
.RS
.B "Note:"
\fBSELECT FOR UPDATE\fR コマンドは、ターゲットテーブルに対してこのモードのロックを獲得します (他の、参照はされているが \fBFOR UPDATE\fR としては選択されていないテーブルの ACCESS SHARE ロックに加えて)。
.RE
.sp
.TP
\fBROW EXCLUSIVE MODE\fR
SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVEモードに競合します。
.sp
.RS
.B "Note:"
\fBUPDATE\fR、\fBDELETE\fR、および \fBINSERT\fR の各コマンドは、ターゲットテーブルに対してこのロックモードを獲得します (その他の参照テーブル用の ACCESS SHARE ロックに加えて)。 一般に、このロックモードはテーブル内のデータを変更する問い合わせによって獲得されます。
.RE
.sp
.TP
\fBSHARE UPDATE EXCLUSIVE MODE\fR
SHARE UPDATE EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE モードに競合します。 このモードはスキーマの変更と \fBVACUUM\fR の同時実行からテーブルを保護します。
.sp
.RS
.B "Note:"
(\fBFULL\fR なしの) \fBVACUUM\fR によって獲得されます。
.RE
.sp
.TP
\fBSHARE MODE\fR
ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE モードに競合します。 このモードは同時データ変更からテーブルを保護します。
.sp
.RS
.B "Note:"
\fBCREATE INDEX\fR によって獲得されます。
.RE
.sp
.TP
\fBSHARE ROW EXCLUSIVE MODE\fR
ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE モードに競合します。
.sp
.RS
.B "Note:"
PostgreSQL コマンドでは、このロックモードを自動的には獲得しません。
.RE
.sp
.TP
\fBEXCLUSIVE MODE\fR
ROW SHARE、ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE モードに競合します。このモードでは同時 ACCESS SHARE のみを許可します。つまりトランザクションがこのロックモードを持っていると、テーブルの読み取りのみの同時処理が許可されます。
.sp
.RS
.B "Note:"
PostgreSQL コマンドでは、このロックモードを自動的には獲得しません。
.RE
.sp
.TP
\fBACCESS EXCLUSIVE MODE\fR
すべてのロックモードと競合します。 このモードを使用すると、どのような場合でもこの権限を持っているトランザクションのみがテーブルにアクセスできます。
.sp
.RS
.B "Note:"
\fBALTER TABLE\fR、\fBDROP TABLE\fR、\fBVACUUM FULL\fR の各文によって獲得されます。 モードを明示的に指定していない \fBLOCK TABLE\fR 文では、これがデフォルトのロックモードになります。
.RE
.sp
.PP
.SS "出力"
.PP
.TP
\fBLOCK TABLE\fR
ロックの獲得に成功しました。
.TP
\fBERROR \fIname\fB: Table does not exist.\fR
\fIname\fR が存在しない場合に返されるメッセージです。
.PP
.SH "説明"
.PP
\fBLOCK TABLE\fR はテーブルレベルのロックを獲得し、必要であれば競合するロックが解除されるのを待ちます。 ロックは、一度取得されると現行のトランザクションが完了するまで保持されます。 (\fBUNLOCK TABLE\fR コマンドはありません。ロックはトランザクションの終了時に常に解除されます。)
.PP
テーブルを参照するコマンドのために自動的にロックを獲得する場合、PostgreSQL は常に使用可能な一番弱いロックモードを使用します。\fBLOCK TABLE\fR はより制限の強いロックが必要な場合のために用意されています。
.PP
例えば、アプリケーションが隔離レベル READ COMMITTED でトランザクションを実行し、そのトランザクションの期間中テーブルのデータの安定性を確実にする必要がある場合を考えてみます。これを達成するために、 問い合わせ実行前にテーブル全体にSHAREロックモードを使用することができます。 これにより、データが同時に変更されるのを防ぎ、それ以降のテーブルの読み取りを安定させることができます。なぜなら SHARE ロックモードは書き込み側が獲得する ROW EXCLUSIVE ロックと競合するので \fBLOCK TABLE \fIname\fB IN SHARE MODE\fR 文は、ROW EXCLUSIVE の同時保持者のうち誰かがコミットまたはロールバックするのを待つからです。 このように、一度ロックを獲得すると、コミットされていない状態の書き込みはなくなり、ユーザがロックを解除するまで誰も書き込みを開始することはできません。
.sp
.RS
.B "Note:"
隔離レベル SERIALIZABLE でのトランザクション実行中にこれと同様の効果を得るには、DML 文を実行する前に \fBLOCK TABLE\fR 文を実行する必要があります。 シリアライザブルなトランザクション側から参照するデータの状態は、最初の DML 文が開始された時点で固定されます。 後の \fBLOCK\fR も同時書き込みを防ぎますが、トランザクションの読み込み対象のデータがコミットされた最新の値に対応しているかは保証されません。
.RE
.sp
.PP
このようなトランザクションでテーブル内データを変更する場合は、SHARE モードではなく SHARE ROW EXCLUSIVE ロックモードを使用する必要があります。 これによって、この種のトランザクションが同時に複数実行されることがなくなります。 SHARE ROW EXCLUSIVE を使用しないと、デッドロックが発生する可能性があります。 つまり、2 つのトランザクションの両方が SHARE モードを獲得したものの、実際に更新を行うための ROW EXCLUSIVE モードを獲得することができないような状態になる可能性があります。 (トランザクション自身のロックは競合しないので、トランザクションは SHARE モードを保持している時に ROW EXCLUSIVE を獲得することができます。しかし、他のトランザクションが SHARE モードを保持している時には ROW EXCLUSIVE を獲得することはできません。)
.PP
デッドロック状態を避けるために、2 つの一般的なルールがあります。
.TP 0.2i
\(bu
トランザクションは同じオブジェクトに同じ順番でロックを獲得する必要があります。

例えば、あるアプリケーションが（同じトランザクションの中で）R1 行を更新し、そして R2 行を更新する場合、別のアプリケーションは （ 1 つのトランザクションの中で）後で R1 行を更新する予定があるならば、R2 行を更新してはいけません。その代わりに、最初のアプリケーションと同じ順番で R1 行と R2 行を更新しなければなりません。
.TP 0.2i
\(bu
単一のオブジェクトに対して複数のロックモードが必要な場合は、トランザクションは常に最も制限の強いモードをまず獲得しなければなりません。

このルールの例は、上の、SHARE モードよりも SHARE ROW EXCLUSIVE モードを使用すべきであるという議論にて記述しています。
.PP
PostgreSQL はデッドロックを検出し、少なくても 1 つの待ち状態のトランザクションを、デッドロックを解消するためにロールバックします。 このルールに厳密に従ったアプリケーションを作成するのが実用的でない場合は、トランザクションがデッドロックによってアボートした場合に再試行するようにするという手段もあります。
.PP
.PP
複数のテーブルをロックする時、LOCK a, b; コマンドは、LOCK a; LOCK b; と同じです。テーブルは \fBLOCK\fR コマンドで指定された順番で、一つ一つロックされます。
.PP
.SS "注釈"
.PP
LOCK ... IN ACCESS SHARE MODE には対象テーブルに対するSELECT 権限が必要です。その他の形の \fBLOCK\fR には全て UPDATE、DELETE、またはその両方の権限が必要です。
.PP
\fBLOCK\fR は通常、トランザクションブロック(\fBBEGIN\fR...\fBCOMMIT\fR) の内側でのみ使用されます。ロックはトランザクションの終了後すぐに削除されるからです。 トランザクションブロック外部の\fBLOCK\fR コマンドはそれ自体がトランザクションになりますので、ロックは入手された後すぐに削除されます。
.PP
RDBMS ロックは以下の標準用語を使います。
.TP
\fBEXCLUSIVE\fR
排他的ロックは、同種のほかのロックが付与されることを防ぎます。
.TP
\fBSHARE\fR
共有ロックは、同種のロックを他が持つことを認めます。 しかし、対応する排他的ロックが認められることを防ぎます。
.TP
\fBACCESS\fR
テーブルスキーマをロックします。
.TP
\fBROW\fR
各行を個別にロックします。
.PP
.PP
PostgreSQL はこの用語に厳密には従っていません。 \fBLOCK TABLE\fR は、テーブルレベルのロックのみを扱うので、モード名に ROW が含まれるのは適切ではありません。 これらのモード名は、ロックされたテーブル内での行レベルのロックを獲得しようとしていると、通常は解釈されてしまうでしょう。 また、ROW EXCLUSIVE モードも共有可能なテーブルロックであるため、厳密にはこの命名に従っていません。 \fBLOCK TABLE\fR に関しては、すべてのロックモードが同じ意味を持っていることに注意してください。違うのは、どのモードがどのモードと競合するかという規則だけです。
.SH "使用方法"
.PP
外部キーテーブルへの挿入を行なう際に、プライマリキーテーブルへの SHARE ロックを獲得します。
.sp
.nf
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;
   
.sp
.fi
.PP
削除操作を行なう際にプライマリキーテーブルの SHARE ROW EXCLUSIVE ロックを取得します。
.sp
.nf
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;
   
.sp
.fi
.SH "互換性"
.SS "SQL92"
.PP
SQL92 には \fBLOCK TABLE\fR は ありません。 その代わりにトランザクションの同時性レベルを指定する \fBSET TRANSACTION\fR を使用します。PostgreSQL はこれ もサポートしています。 詳細については SET TRANSACTION [\fBset_transaction\fR(l)] を参照して下さい。
.PP
ACCESS SHARE、ACCESS EXCLUSIVE、SHARE UPDATE EXCLUSIVE ロックモードを除き、PostgreSQL のロックモードと\fBLOCK TABLE\fR 構文はOracle(TM) のものと互換性があります。
