sp_getapplock (Transact-SQL)

適用対象:SQL ServerAzure SQL DatabaseAzure SQL Managed Instance

アプリケーション リソースにロックを設定します。

Transact-SQL 構文表記規則

構文

  
sp_getapplock [ @Resource = ] 'resource_name' ,  
     [ @LockMode = ] 'lock_mode'   
     [ , [ @LockOwner = ] 'lock_owner' ]   
     [ , [ @LockTimeout = ] 'value' ]  
     [ , [ @DbPrincipal = ] 'database_principal' ]  
[ ; ]  

引数

[ @Resource= ] 'resource_name'
ロック リソースを識別する名前を指定する文字列です。 アプリケーション側では、リソース名が一意になるよう管理されている必要があります。 指定された名前は、SQL Server ロック マネージャーに格納できる値に内部的にハッシュされます。 resource_nameは nvarchar(255) で、既定値はありません。 リソース文字列が nvarchar(255) より長い場合は、nvarchar(255)切り捨てられます。

resource_nameはバイナリ比較であるため、現在のデータベースの照合順序設定に関係なく大文字と小文字が区別されます。

Note

アプリケーション ロックが取得されると、プレーン テキストで抽出できるのは最初の 32 文字のみとなり、残りの部分はハッシュされます。

[ @LockMode= ] 'lock_mode'
特定のリソースに対して取得されるロック モードです。 lock_modeは varchar(32) で、既定値はありません。 値には、Shared、Update、IntentSharedIntentExclusive、Exclusive のいずれかを指定できます。 詳細については、「ロック モード」を参照してください

[ @LockOwner= ] 'lock_owner'
ロックの所有者を指定します。これはロックが要求されたときの lock_owner 値です。 lock_ownerは varchar(32) です。 この値は Transaction (既定値) または Session のいずれかです。 lock_owner値が Transaction場合、既定で、または明示的に指定されている場合、sp_getapplockはトランザクション内から実行する必要があります。

[ @LockTimeout= ] 'value'
ロック タイムアウト値 (ミリ秒単位) です。 既定値は、@@LOCK_TIMEOUTによって返される値と同じです。 値が -1 (既定値) の場合は、タイムアウトはなく、無期限に待機します。 ロック要求がすぐに許可できないときにロックを待機するのではなく、-1 のリターン コードを返す必要があることを示すには、0 を指定します。

[ @DbPrincipal= ] 'database_principal'
データベース内のオブジェクトに対するアクセス許可を持つユーザー、ロール、またはアプリケーション ロールです。 関数を正常に呼び出すには、関数の 呼び出し元が database_principal、dbo、または固定データベース ロールdb_ownerのメンバーである必要があります。 既定値はパブリックです。

リターン コードの値

>= 0 (成功)、または < 0 (失敗)

Value 結果
0 ロックが同時に許可されました。
1 互換性のない他のロックが解放されるのを待機してから、ロックが許可されました。
-1 ロック要求がタイムアウトしました。
-2 ロック要求が取り消されました。
-3 ロック要求がデッドロックの対象になりました。
-999 パラメーターの検証またはその他の呼び出しエラーを示します。

解説

リソースに配置されたロックは、現在のトランザクションまたは現在のセッションに関連付けられます。 現在のトランザクションに関連付けられたロックは、トランザクションがコミットまたはロールバックされるときに解放されます。 セッションに関連付けられているロックは、セッションがログアウトされると解放されます。何らかの理由でサーバーがシャットダウンすると、すべてのロックが解放されます。

sp_getapplockによって作成されたロック リソースは、セッションの現在のデータベースに作成されます。 各ロック リソースは、次の値の組み合わせによって識別されます。

  • ロック リソースを含むデータベースのデータベース ID。

  • パラメーターで @DbPrincipal 指定されたデータベース プリンシパル。

  • パラメーターで @Resource 指定されたロック名。

@DbPrincipal パラメーターで指定されるデータベース プリンシパルのメンバーだけが、そのプリンシパルを指定しているアプリケーション ロックを取得できます。 dbo ロールと db_owner ロールのメンバーは、暗黙的にすべてのロールのメンバーと見なされます。

ロックは、sp_releaseapplock で明示的に解放できます。 アプリケーションで、同じロック リソースに対して sp_getapplock が複数回呼び出される場合は、同じ回数だけ sp_releaseapplock を呼び出して、ロックを解放する必要があります。 ロック所有者がロックを使用してロックを Transaction 開くと、そのロックは、トランザクションがコミットまたはロールバックされたときに解放されます。

sp_getapplock が同じロック リソースに対して複数回呼び出されても、その要求で指定されるロック モードが既存のモードと異なる場合、リソースでは 2 つのロック モードが混在することになります。 このため、ロック モードは多くの場合、既存のモードと新しく要求されたモードのうち、より強力なモードに昇格します。 このより強力なロック モードは、ロックが最終的に解放されるまで保持されます。 たとえば、次の一連の呼び出しでは、リソースはモードではなくモードでShared保持Exclusiveされます。

USE AdventureWorks2022;  
GO  
BEGIN TRANSACTION;  
DECLARE @result int;  
EXEC @result = sp_getapplock @Resource = 'Form1',   
               @LockMode = 'Shared';  
EXEC @result = sp_getapplock @Resource = 'Form1',   
               @LockMode = 'Exclusive';  
EXEC @result = sp_releaseapplock @Resource = 'Form1';  
COMMIT TRANSACTION;  
GO  

アプリケーション ロック時にデッドロックが発生すると、アプリケーション ロックを要求したトランザクションはロールバックされません。 戻り値の結果として必要になる可能性があるロールバックは、手動で行う必要があります。 したがって、ある特定の値 (たとえば -3) が返された場合に ROLLBACK TRANSACTION または代替の操作が開始できるように、コードにはエラー チェックを含めることをお勧めします。

例を次に示します。

USE AdventureWorks2022;  
GO  
BEGIN TRANSACTION;  
DECLARE @result int;  
EXEC @result = sp_getapplock @Resource = 'Form1',   
               @LockMode = 'Exclusive';  
IF @result = -3  
BEGIN  
    ROLLBACK TRANSACTION;  
END  
ELSE  
BEGIN  
    EXEC @result = sp_releaseapplock @Resource = 'Form1';  
    COMMIT TRANSACTION;  
END;  
GO  

SQL Server では、現在のデータベース ID を使用してリソースを修飾します。 そのため、異なるデータベースで同じパラメーター値を使用しても、sp_getapplockが実行された場合、結果は個別のリソースに対して個別のロックになります。

sys.dm_tran_locks動的管理ビューまたはsp_lock システム ストアド プロシージャを使用してロック情報を調べるか、SQL Server プロファイラーを使用してロックを監視します。

アクセス許可

public ロールのメンバーシップが必要です。

次の例では、現在のトランザクションに関連付けられている共有ロックを、Form1 データベースのリソース AdventureWorks2022 に設定します。

USE AdventureWorks2022;  
GO  
BEGIN TRAN;  
DECLARE @result int;  
EXEC @result = sp_getapplock @Resource = 'Form1',   
               @LockMode = 'Shared';  
COMMIT TRAN;  
GO  

次の例では、データベース プリンシパルとして指定します dbo

BEGIN TRAN;  
EXEC sp_getapplock @DbPrincipal = 'dbo', @Resource = 'AdventureWorks2022',   
     @LockMode = 'Shared';  
COMMIT TRAN;  
GO  

参照

APPLOCK_MODE (Transact-SQL)
APPLOCK_TEST (Transact-SQL)
sp_releaseapplock (Transact-SQL)