説明
LOCK TABLE
はテーブルレベルのロックを取得し、必要に応じて競合するロックが解放されるのを待ちます。 NOWAIT
が指定されている場合、LOCK TABLE
は目的のロックを取得するのを待機しません。 一旦取得されると、ロックは現在のトランザクションの残りのために保持される。 (UNLOCK TABLE
コマンドはありません。ロックはトランザクション終了時に常に解放されます。)
ビューがロックされると、ビュー定義クエリに表示されるすべてのリレーションも、同じロックモードで再帰的にロックされます。
テーブルを参照するコマンドのロックを自動的に取得する場合、PostgreSQLalwaysは可能な限り制限の少ないロックモードを使用します。LOCK TABLE
は、より制限的なロックが必要な場合を提供します。 たとえば、アプリケーションがREAD COMMITTED
分離レベルでトランザクションを実行し、テーブル内のデータがトランザクションの期間中安定していることを保証する必要があるとします。 これを実現するには、クエリを実行する前にテーブルに対してSHARE
ロックモードを取得します。 SHARE
ロックモードはライターが取得したROW EXCLUSIVE
ロックと競合し、lock TABLEIN SHARE mode
ステートメントはROW EXCLUSIVE
モードロックの同時保持者がコミットまたはロールバックするまで待機するため、同時データ変更を防止し、その後のテーブルの読み取りでコミットデータの安定したビューを確認できます。 したがって、ロックを取得すると、未コミットの書き込みはなくなります。さらに、ロックを解放するまで開始できません。
REPEATABLE READ
またはSERIALIZABLE
分離レベルでトランザクションを実行しても同様の効果を得るには、SELECT
またはデータ変更ステートメントを実行する前にLOCK TABLE
ステートメントを実行する必要があります。 REPEATABLE READ
またはSERIALIZABLE
トランザクションのデータのビューは、最初のSELECT
またはデータ変更ステートメントの開始時に凍結されます。 トランザクションの後のLOCK TABLE
は同時書き込みを防止しますが、トランザクションが読み取るものが最新のコミットされた値に対応することは保証されません。
この種類のトランザクションがテーブル内のデータを変更しようとしている場合は、SHARE
モードではなくSHARE ROW EXCLUSIVE
ロックモードを使用する必要があります。 これにより、同じタイプのトランザクションが同時に複数実行されることがなくなります。 これがないと、デッドロックが発生する可能性があります。2つのトランザクションが両方ともSHARE
モードを取得し、ROW EXCLUSIVE
モードを取得して実際に更新を実行できなくなる可能性があります。 (トランザクション自体のロックは競合しないため、トランザクションはSHARE
モードを保持している場合はROW EXCLUSIVE
モードを取得できますが、他の誰かがSHARE
モードを保持している場合は取得できません。) デッドロックを回避するには、すべてのトランザクションが同じオブジェクトのロックを同じ順序で取得するようにします。1つのオブジェクトに複数のロックモードが含まれている場合、トランザクションは常に最も制限の厳しいモードを最初に取得する必要があります。
概要
LOCK [テーブル] [のみ] name [ * ] [, ...] [ロックモードモード] [ NOWAIT]
ここで、lockmodeは次のいずれかです。
アクセスシェア | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE
| シェア | シェアROW EXCLUSIVE | 排他的 | アクセス排他的
パラメーター
名前
ロックする既存のテーブルの名前 (オプションでスキーマ修飾) 。 テーブル名の前に
ONLY
を指定した場合、そのテーブルのみがロックされます。ONLY
が指定されていない場合、テーブルとそのすべての子孫テーブル (存在する場合) がロックされます。 必要に応じて、テーブル名の後に*
を指定して、子孫テーブルが含まれることを明示的に示すことができます。コマンド
LOCK TABLE a, b;
は、LOCK TABLE a; LOCK TABLE b;
と等価である。 テーブルは、LOCK TABLE
コマンドで指定された順序で1つずつロックされます。lockmode
ロックモードは、このロックが競合するロックを指定します。
ロックモードが指定されていない場合、最も制限の厳しいモードである
ACCESS EXCLUSIVE
が使用されます。NOWAIT
競合するロックが解放されるまで
LOCK TABLE
が待機しないことを指定します。指定されたロックを待機せずにすぐに取得できない場合、トランザクションは中止されます。
注
テーブルをロックするには、ユーザーが指定された
ロックモード
に対する権限を持っているか、テーブルの所有者またはスーパーユーザーである必要があります。 ユーザーがテーブルに対してUPDATE
、DELETE
、またはTRUNCATE
権限を持っている場合、ロックモード
は許可されます。 ユーザーがテーブルに対してINSERT
権限を持っている場合、ROW EXCLUSIVE MODE
が許可されます。 ユーザーがテーブルに対してSELECT
権限を持っている場合、アクセス共有モード
が許可されます。ビューに対してロックを実行するユーザーは、ビューに対して対応する特権を持っている必要があります。 さらに、デフォルトでは、ビューの所有者は、基礎となるベースリレーションに対して関連する権限を持つ必要がありますが、ロックを実行するユーザーは、基礎となるベースリレーションに対する権限を必要としません。 ただし、ビューの
security_invoker
がtrue
に設定されている場合、ロックを実行するユーザーは、ビューの所有者ではなく、基になるベースリレーションに対して関連する権限を持つ必要があります。LOCK TABLE
はトランザクションブロック以外では役に立たない。ロックはステートメントの完了までしか保持されない。 トランザクションブロックの外部でLOCK
が使用されている場合、PostgreSQLはエラーを報告します。 トランザクションブロックを定義するには、BEGINとCOMMIT (またはROLLBACK) を使用します。LOCK TABLE
はテーブルレベルのロックのみを扱うため、ROW
を含むモード名はすべて誤った名前です。 これらのモード名は、一般に、ロックされたテーブル内の行レベルロックを取得するというユーザの意図を示すものとして読まれるべきである。 また、ROW EXCLUSIVE
モードは、共有可能なテーブルロックです。lock TABLE
に関する限り、すべてのロックモードは同一のセマンティクスを持ち、どのモードがどのモードと競合するかに関するルールのみが異なることに注意してください。
例
外部キーテーブルへの挿入を実行するときに、主キーテーブルのSHARE
ロックを取得します。
仕事を始める;
シェアモードでテーブルフィルムをロック;
フィルムからのSELECT id
名前='スターウォーズ: エピソードI-ファントムメナス';
-レコードが返されなかった場合はROLLBACKを実行します
films_user_comments値に挿入する
(_id_、'GREAT! 私は長い間それを待っていました!);
COMMITの仕事;
削除操作を実行するときに、プライマリキーテーブルに対してSHARE ROW EXCLUSIVE
ロックを実行します。
仕事を始める;
SHARE ROW EXCLUSIVEモードでテーブルフィルムをロックします。films_user_commentsから削除する
(フィルムからの選択id WHEREレーティング <5);
映画から削除するWHEREレーティング <5;
COMMITの仕事;