ロックについて
マルチバージョン コンカレンシー制御 (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 ではない) |
共有 | CREATE INDEX (CONCURRENTLY ではない) コマンド |
SHARE ROW EXCLUSIVE | CREATE TRIGGER コマンドと一部の ALTER TABLE コマンド |
EXCLUSIVE | REFRESH MATERIALIZED VIEW CONCURRENTLY コマンド |
ACCESS EXCLUSIVE | 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 | Blocked | |||||||
要求された ROW SHARE | Blocked | Blocked | ||||||
要求された ROW EXCLUSIVE | Blocked | Blocked | Blocked | Blocked | ||||
要求された SHARE UPDATE EXCLUSIVE | Blocked | Blocked | Blocked | Blocked | Blocked | |||
要求された SHARE | Blocked | Blocked | Blocked | Blocked | Blocked | |||
要求された SHARE ROW EXCLUSIVE | Blocked | Blocked | Blocked | Blocked | Blocked | Blocked | ||
要求された EXCLUSIVE | Blocked | Blocked | Blocked | Blocked | Blocked | Blocked | Blocked | |
要求された ACCESS EXCLUSIVE | Blocked | Blocked | Blocked | Blocked | Blocked | Blocked | Blocked | Blocked |
行レベルのロック
行レベルのロックはより細かく、同じ行にアクセスしている別のトランザクションにのみ影響します。 このロックの種類によりコンカレンシーが向上しますが、多数のロックを取得、削除することはパフォーマンスに悪影響を及ぼします。 行レベルのロックは PostgreSQL によって自動的に取得され、手動では適用されません。
Azure Database for PostgreSQL には 4 種類の行レベル ロックがあり、ブロックする必要がある他のロックの種類に応じて取得されます。
-- | 既存の FOR KEY SHARE | 既存の FOR SHARE | 既存の FOR NO KEY UPDATE | 既存の FOR UPDATE |
---|---|---|---|---|
要求された KEY SHARE | Blocked | |||
要求された FOR SHARE | Blocked | Blocked | ||
要求された FOR NO KEY UPDATE | Blocked | Blocked | Blocked | |
要求された FOR UPDATE | Blocked | Blocked | Blocked | Blocked |
ページ レベルのロック
ページ レベルのロックは、複数の行で通常は構成されるデータ ページに影響します。 PostgreSQL プロセスではページ レベルのロックが使用されますが、通常、アプリケーション開発者はこの種類のロックを必要としません。
ロックを手動で適用し、現在のロックを表示する
テーブル レベルのロックを手動で適用するには、LOCK コマンドを必要なロック モードで使用します。 LOCK コマンドはトランザクション内に存在する必要があり、トランザクションの完了時にロックが解放されます。 次に例を示します。
BEGIN TRANSACTION;
LOCK TABLE humanresources.department IN ROW EXCLUSIVE MODE;
COMMIT;
データベースで現在保持されているロックを表示するには、pg_locks を使用します。 たとえば、すべての現在のロックを表示するには、次のコマンドを使用します。
SELECT * FROM pg_locks;