ロックを理解する

完了

マルチバージョン コンカレンシー制御 (MVCC) は、ほとんどのシナリオに適したコンカレンシー設定を提供します。 ただし、影響を受ける行と特定のロック レベルを正確に制御する特定のロックがアプリケーションに必要な場合は、明示的なロック モードによって、このきめ細かい制御が有効になります。

Azure Database for PostgreSQL には、明示的なロック、テーブル レベルのロック、行レベルのロック、ページ レベルのロックの 3 種類があります。 最初のトランザクションはロックを要求し、受け入れられた場合は、要求されたロックが既存のロックになります。 別のトランザクションが同じデータに対してロックを解除しようとすると、元のトランザクションと競合しない場合、ロックが付与されます。

たとえば、2 つのトランザクションで、SELECT ステートメントを使用して同じデータに対して同時にクエリを実行できます。 これらの要求では ACCESS SHARE ロックが使用され、両方とも許可されます。 別のシナリオでは、あるトランザクションが SELECT ステートメントと ACCESS SHARE ロックを使用してデータに対してクエリを実行していますが、同時に、別のトランザクションが同じテーブルを削除しようとします。 テーブルを削除するには、このシナリオでは許可されない ACCESS EXCLUSIVE ロックが必要です。

テーブルレベルのロック

テーブル レベルのロックは、名前に ROW がある場合でも、テーブル全体のロックを取得します。 テーブル自体が変更されている場合は、テーブル全体のロックが必要になる場合や、多くの行レベルのロックを取り出すよりも効率的な場合があります。

Azure Database for PostgreSQL には 8 種類のテーブル レベルロックがあり、これらの種類のロックを取得する SQL コマンドは次のとおりです。

ロック モード 取得方法
ACCESS SHARE SELECT コマンド
ROW SHARE SELECT FOR UPDATE および SELECT FOR SHARE コマンド
ROW EXCLUSIVE UPDATE、DELETE、INSERT の各コマンド
SHARE UPDATE EXCLUSIVE ANALYZE、CREATE INDEX CONCURRENTLY、CREATE STATISTICS、COMMENT ON、REINDEX CONCURRENTLY コマンド、一部の ALTER INDEX および ALTER TABLE コマンド、VACUUM (FULL ではない)
SHARE CREATE INDEX (CONCURRENTLY ではない) コマンド
SHARE ROW EXCLUSIVE CREATE TRIGGER コマンドと一部の ALTER TABLE コマンド
EXCLUSIVE REFRESH MATERIALIZED VIEW CONCURRENTLY コマンド
アクセス限定 DROP TABLE、REINDEX、TRUNCATE、CLUSTER、REFRESH MATERIALIZED VIEW (CONCURRENTLY ではない) コマンド、ほとんどの ALTER INDEX および ALTER TABLE コマンド、VACUUM FULL

既存のロックの各種類は、他の要求されたロックの取得をブロックします。 次の表に、他のロックの取得をブロックするロックを示します。

-- 既存の ACCESS SHARE 既存の ROW SHARE 既存の ROW EXCLUSIVE 既存の SHARE UPDATE EXCLUSIVE 既存の SHARE 既存の SHARE ROW EXCL 既存の EXCLUSIVE 既存の ACCESS EXCLUSIVE
要求された ACCESS SHARE ブロックされました
要求された ROW SHARE ブロックされました ブロックされました
要求された ROW EXCLUSIVE ブロックされました ブロックされました ブロックされました ブロックされました
要求された SHARE UPDATE EXCLUSIVE ブロックされました ブロックされました ブロックされました ブロックされました ブロックされました
要求された SHARE ブロックされました ブロックされました ブロックされました ブロックされました ブロックされました
要求された SHARE ROW EXCLUSIVE ブロックされました ブロックされました ブロックされました ブロックされました ブロックされました ブロックされました
要求された EXCLUSIVE ブロックされました ブロックされました ブロックされました ブロックされました ブロックされました ブロックされました ブロックされました
要求された ACCESS EXCLUSIVE ブロックされました ブロックされました ブロックされました ブロックされました ブロックされました ブロックされました ブロックされました ブロックされました

行レベルのロック

行レベルのロックはより細かく、同じ行にアクセスしている別のトランザクションにのみ影響します。 このロックの種類によりコンカレンシーが向上しますが、多くのロックを取得および削除すると、パフォーマンスに悪影響が及びます。 行レベルのロックは PostgreSQL によって自動的に取得され、手動では適用されません。

Azure Database for PostgreSQL には 4 種類の行レベル ロックがあり、ブロックする必要がある他のロックの種類に応じて取得されます。

-- 既存の FOR KEY SHARE 既存の FOR SHARE 既存の FOR NO KEY UPDATE 既存の FOR UPDATE
キー共有のためにリクエストされました ブロックされました
要求された FOR SHARE ブロックされました ブロックされました
要求された FOR NO KEY UPDATE ブロックされました ブロックされました ブロックされました
要求された FOR UPDATE ブロックされました ブロックされました ブロックされました ブロックされました

ページ レベルのロック

ページ レベルのロックは、通常は複数の行で構成されるデータのページに影響します。 PostgreSQL プロセスではページ レベルのロックが使用されますが、通常、アプリケーション開発者はこの種類のロックを必要としません。

ロックの手動適用と現在のロックの表示

テーブル レベルのロックを手動で適用するには、LOCK コマンドを必要なロック モードで使用します。 LOCK コマンドはトランザクション内に存在する必要があり、トランザクションの完了時にロックが解放されます。 例えば次が挙げられます。

BEGIN TRANSACTION;
LOCK TABLE humanresources.department IN ROW EXCLUSIVE MODE;
COMMIT;

データベースで現在保持されているロックを表示するには、 pg_locksを使用します。 たとえば、現在のすべてのロックを表示するには、次のコマンドを使用します。

SELECT * FROM pg_locks;