説明
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の仕事;