LOCK [ TABLE ] name LOCK [ TABLE ] name IN [ ROW | ACCESS ] { SHARE | EXCLUSIVE } MODE LOCK [ TABLE ] name IN SHARE ROW EXCLUSIVE MODE
ロックを行なう既存のテーブル名。
Note: このモードでは問い合わせが行なわれるテーブル全体のロックを自 動的に獲得します。
これは最も制限の弱いロックモードです。 ACCESS EXCLUSIVE モードとのみコンフリクトします。 あるテーブルに対する ALTER TABLE、DROP TABLE、 VACUUM 文の同時実行からそのテーブルを保護 することが目的です。
Note: 任意の SELECT ...FOR UPDATE 文によって自動的 に獲得されます。 共有ロックですが、後に ROW EXCLUSIVE ロックに上がる可能性があり ます。
EXCLUSIVE と ACCESS EXCLUSIVE ロックモードとコンフリクトします。
Note: UPDATE、DELETE、 INSERT 文によって自動的に獲得されます。
SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE モ ードとコンフリクトします。
Note: CREATE INDEX 文によって自動的に獲得されます。 共有(share)は、テーブル全体をロックすることを意味します。
ROW EXCLUSIVE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE モードとコンフリクトします。このモードは同時更新からテーブルを保 護します。
Note: これは EXCLUSIVE モードに似ていますが、他所にて SHARE ROW モードでロックすることができます。
ROW EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、 ACCESS EXCLUSIVE モードとコンフリクトします。
Note: このモードは SHARE ROW EXCLUSIVE よりもっと制限が強いも のです。 このモードは全ての ROW SHARE/SELECT...FOR UPDATE 問い合 わせの同時実行をブロックします。
ROW SHARE、ROW EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、 EXCLUSIVE、ACCESS EXCLUSIVE モードとコンフリクトします。
Note: ALTER TABLE、 DROP TABLE, VACUUM 文 によって自動的に獲得されます。 このモードは最も制限の強いロックモードで、他の全てのロック モードとコンフリクトし、全ての同時実行操作からロックされた テーブルを保護します。
Note: このロックモードは条件を持たない (つまり、明示的なロックモー ドオプションが付いていない) LOCK TABLE に よっても獲得されます。
LOCK TABLE は、トランザクション期間において、ある テーブルへの同時アクセスを制御します。 Postgres は可能である限り、常に最も制限 の弱いロックモードを使用します。より強い制限を持つロックを必要とす る場合のために LOCK TABLE が用意されています。
RDBMS におけるロックにて、以下の用語が使用され ます。
排他的ロック。これは他がロックを獲得することを許しません。
他が共有ロックを獲得することを許可します。 他が EXCLUSIVE ロックを獲得することを許しません。
テーブルスキーマをロックします。
個々の行をロックします。
Note: EXCLUSIVE、SHAREいずれの指定も無い場合、EXCLUSIVE ロックとみな されます。 ロックはそのトランザクション期間中にわたって有効です。
例えば、アプリケーションが隔離レベル READ COMMITTED でトランザクシ ョンを実行し、そのトランザクションの間テーブルにデータが存在するこ とを確実にする必要がある場合を考えてみます。 これを達成するために、問い合わせ実行前にテーブル全体に SHARE ロック モードを使用することができます。 これは同時変更からデータを保護するとともに、現在の実状態を維持したテーブル全体 に対して読みとり操作を引続き行えるようにします。 SHARE ロックモードは、書き込み側によって獲得されるあらゆる ROW EXCLUSIVE とコンフリクトし、実行した LOCK TABLE name IN SHARE MODE 文は同時書き込み操作のコミットまたはロールバックが終るまで待つからです。
Note: トランザクションが隔離レベル SERIALIZABLE で実行している時に、現 在の実状態のデータを読むためには、何らかの DML 文を実行するより前 に LOCK TABLE 文を実行する必要があります。このとき、そのトランザク ションはどんな同時変更を自身で認識できるかを定義します。
上の要求事項に加え、トランザクションがテーブル内のデータを変更しよ うとするのであれば、SHARE ROW EXCLUSIVE ロックモードを獲得して、次の デッドロック状態を防止しなければなりません。 2 つの同時トランザクションがテーブルを SHARE モードでロックし、 そしてテーブル内のデータを変更しようとする場合、両者は (暗黙 的に) ROW EXCLUSIVE ロックモードを取得しようとしますが、このロック モードは現在獲得されている SHARE ロックとコンフリクトします。
上で取り上げたデッドロック (2 つのトランザクションがお互いに待ってい る状態)の問題に関してですが、デッドロック状態を防ぐために以下の 2 つの一般的なルールに従わなければなりません。
トランザクションは同じオブジェクトに同じ順番でロックを獲得する必 要があります。
例えば、あるアプリケーションが (同じトランザクションの中で) 行 R1 を更新し、そして行 R2 を更新する場合、別のアプリケーションは ( 1 つのトランザクションの中で)後で行 R1 を更新する予定がある ならば、行 R2 を更新してはいけません。その代わりに、最初のアプリ ケーションと同じ順番で行 R1 と行 R2 を更新しなければなりません。
トランザクションは、2 つのロックモードの内の 1 つがそのモード自身 とコンフリクトする場合 (つまり同時に 1 つのトランザクションしかそ のロックを保持できない場合) にのみ、2 つのコンフリクトするロック モードを獲得しなければなりません。複数のロックモードが必要な場合 は、トランザクションは常に最も制限の強いモードをまず獲得しなけれ ばなりません。
このルールの例は、既にSHARE モードよりも SHARE ROW EXCLUSIVE モ ードを使用すべきであるという部分で指摘済みです。
Note: Postgres はデッドロックを検出し、少なく ても 1 つの待ち状態のトランザクションを、デッドロックを解消するた めにロールバックします。
外部キーテーブルへの挿入を行なう際のプライマリキーテーブルへの 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 には LOCK TABLE は ありません。その代わりにトランザクションの同時性レベルを指定する SET TRANSACTION を使用します。Postgres はこれ もサポートしています。詳細については SET を参照し て下さい。