Lock:Relation
Lock:Relation
イベントは、別のトランザクションによって現在ロックされているテーブルまたはビュー (リレーション) のロックを取得するためにクエリが待っているときに発生します。
サポート対象エンジンバージョン
この待機イベント情報は、Aurora PostgreSQL のすべてのバージョンでサポートされています。
Context
ほとんどの PostgreSQL コマンドは、テーブル内のデータへの同時アクセスを制御するために、暗黙のうちにロックを使用します。また、これらのロックは、アプリケーションコード内でLOCK
コマンドによって明示的に使用することもできます。多くのロックモードは互いに互換性がないため、同じオブジェクトにアクセスしようとしているときにトランザクションをブロックすることがあります。これが起こると、Aurora 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
のロックを、ANALYZE
は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 オートバキュームの使用」を参照してください。
リーダーロックをチェックする
ライターとリーダーの同時セッションが、お互いをブロックするロックを保持しているかどうかを確認できます。これを行う 1 つの方法は、ロックのタイプとリレーションを返すクエリを実行することです。この表では、ライターセッションとリーダーセッションという 2 つの同時セッションに対する一連のクエリを見つけることができます。
再生プロセスは、リーダークエリをキャンセルする前に max_standby_streaming_delay
の期間待機します。例に示すように、100 ms のロックタイムアウトは、デフォルトの max_standby_streaming_delay
である30 秒をはるかに下回っています。ロックは問題になる前にタイムアウトします。
一連のイベント | セッション | コマンドまたは出力 |
---|---|---|
指定された値で READER という環境変数を設定し、このエンドポイントで DB インスタンスに接続しようとします。 |
リーダーセッション |
CLI コマンド:
出力: psql (15devel, server 10.14) Type "help" for help. |
WRITER という環境変数を設定し、このエンドポイントを使用して DB インスタンスに接続しようとします。 |
ライターセッション |
CLI コマンド:
出力: psql (15devel, server 10.14) Type "help" for help. |
ライターセッションはライターインスタンスにテーブル t1 を作成します。 |
ライターセッション |
PostgreSQL クエリ:
|
ライターに競合するクエリがない場合、ACCESS EXCLUSIVE ロックはライターですぐに取得されます。 |
ライターセッション |
|
リーダーセッションは 100 ミリ秒のロックタイムアウトインターバルを設定します。 |
リーダーセッション |
PostgreSQL クエリ:
|
リーダーセッションはリーダーインスタンスでテーブル t1 からデータを読み込もうとします。 |
リーダーセッション |
PostgreSQL クエリ:
サンプル出力: b --- (0 rows) |
ライターセッションが t1 をドロップします。 |
ライターセッション |
PostgreSQL クエリ:
|
クエリがタイムアウトし、リーダーでキャンセルされます。 |
リーダーセッション |
PostgreSQL クエリ:
サンプル出力: ERROR: canceling statement due to lock timeout LINE 1: SELECT * FROM t1; ^ |
リーダーセッションが |
リーダーセッション |
PostgreSQL クエリ:
|
結果は、 |
リーダーセッション |
クエリ結果:
|