Lock:Relation
Lock:Relation
イベントは、別のトランザクションによって現在ロックされているテーブルまたはビュー (リレーション) のロックを取得するためにクエリが待っているときに発生します。
サポート対象エンジンバージョン
この待機イベント情報は、RDS for PostgreSQL のすべてのバージョンでサポートされています。
Context
ほとんどの PostgreSQL コマンドは、テーブル内のデータへの同時アクセスを制御するために、暗黙のうちにロックを使用します。また、これらのロックは、アプリケーションコード内でLOCK
コマンドによって明示的に使用することもできます。多くのロックモードは互いに互換性がないため、同じオブジェクトにアクセスしようとしているときにトランザクションをブロックすることがあります。このイベントが発生すると、RDS for PostgreSQL は Lock:Relation
イベントを生成します。一般的な例をいくつか以下に示します。
ACCESS EXCLUSIVE
のような排他的なロックは、すべての同時アクセスをブロックできます。DROP TABLE
、TRUNCATE
、VACUUM FULL
、CLUSTER
などのデータ定義言語 (DDL) オペレーションは、暗黙のうちにACCESS EXCLUSIVE
ロックを取得します。ACCESS EXCLUSIVE
は、明示的にモードを指定しないLOCK TABLE
ステートメントのデフォルトのロックモードでもあります。テーブル上で
CREATE INDEX (without CONCURRENT)
を使用すると、ROW EXCLUSIVE
ロックを取得するデータ操作言語 (DML) ステートメントUPDATE
、DELETE
、INSERT
と競合します。
テーブルレベルのロックと競合するロックモードの詳細については、PostgreSQL ドキュメントの「明示的なロック
ブロックされたクエリとトランザクションは、通常、次のいずれかの方法でブロックを解除します。
クエリのブロック: アプリケーションがクエリをキャンセルするか、ユーザーがプロセスを終了できます。また、セッションのステートメントタイムアウトやデッドロック検出メカニズムによって、エンジンがクエリを強制終了させることもできます。
トランザクションのブロック: トランザクションが
ROLLBACK
またはCOMMIT
を実行すると、トランザクションはブロックを停止します。ロールバックは、クライアントまたはネットワークの問題によってセッションが切断されたり、終了したときにも自動的に行われます。セッションは、データベースエンジンがシャットダウンされたり、システムがメモリ不足になったりしたときに終了できます。
待機時間が増加する原因の可能性
Lock:Relation
イベントが通常よりも頻繁に発生する場合、パフォーマンスの問題を示している可能性があります。代表的な原因としては、以下が挙げられます。
- テーブルロックの競合による同時セッションの増加
-
競合するロックモードで同じテーブルをロックするクエリによる同時セッションの数が増加する可能性があります。
- メンテナンスオペレーション
-
VACUUM
やANALYZE
のようなヘルスメンテナンスオペレーションは、競合するロックの数を大幅に増加させる可能性があります。VACUUM FULL
はACCESS EXCLUSIVE
のロックを、ANALYSE
はSHARE UPDATE EXCLUSIVE
のロックを取得します。どちらのタイプのロックも、Lock:Relation
待機イベントを引き起こすことがあります。また、マテリアライズドビューのリフレッシュなどのアプリケーションデータのメンテナンスオペレーションも、ブロックされたクエリとトランザクションを増加することもあります。 - リーダーインスタンスをロックする
-
ライターとリーダーが保持しているリレーションロックの間に矛盾がある可能性があります。現在は、
ACCESS EXCLUSIVE
リレーションロックのみが、リーダーインスタンスにレプリケートされます。ただし、ACCESS EXCLUSIVE
リレーションロックは、リーダーが保持するACCESS SHARE
リレーションロックと競合します。これにより、リーダーのロックリレーション待機イベントが増加する可能性があります。
アクション
待機イベントの原因に応じたさまざまなアクションをお勧めします。
SQL ステートメントのブロックによる影響を軽減
SQL ステートメントのブロックによる影響を軽減するには、可能なところではアプリケーションコードを修正します。ブロックを減らすための 2 つの一般的な方法は以下のとおりです。
NOWAIT
オプションを使用する:SELECT
やLOCK
ステートメントなど、一部の SQL コマンドはこのオプションをサポートしています。NOWAIT
指示文は、ロックをすぐに取得できない場合、ロックへのクエリをキャンセルします。この方法は、ブロックされたセッションが、その後ろにあるブロックされたセッションが積み重なるのを防ぐのに役立ちます。例えば、トランザクション A がトランザクション B に保持されているロックを待っているとします。ここで、B がトランザクション C によってロックされているテーブルのロックをリクエストすると、トランザクション C が完了するまでトランザクション A がブロックされる可能性があります。ただし、トランザクション B が C のロックを要求するときに
NOWAIT
を使用する場合、トランザクションBは迅速に失敗し、トランザクション A が無期限に待機する必要がないことを保証できます。SET lock_timeout
を使用する:lock_timeout
値を設定して、SQL ステートメントがリレーションでロックを取得するのを待機する時間を制限します。指定されたタイムアウト時間内にロックが取得されなかった場合、ロックを要求したトランザクションはキャンセルされます。この値はセッションレベルで設定します。
メンテナンスオペレーションの影響を最小限に抑える
VACUUM
やANALYZE
のようなメンテナンスオペレーションは重要です。これらのメンテナンス作業に関連するLock:Relation
待機イベントを見つけても、それらをオフにしないことをお勧めします。次のようなアプローチにより、これらの操作の影響を最小限に抑えることができます。
オフピーク時にメンテナンス操作をマニュアルで実行します。
オートバキュームタスクによる
Lock:Relation
待機をへらすには、必要なオートバキュームチューニングを実行します。オートバキュームのチューニングについては、Amazon RDS ユーザーガイドの「Amazon RDS での PostgreSQL オートバキュームの使用」を参照してください。