sp_getapplock (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 はバイナリで比較されるため、現在のデータベースの照合順序の設定に関係なく、大文字と小文字が区別されます。
注 アプリケーション ロックが取得されると、プレーン テキストで抽出できるのは最初の 32 文字のみとなり、残りの部分はハッシュされます。
[ @LockMode= ] 'lock_mode'
特定のリソースに対して取得されるロック モードを指定します。 lock_mode のデータ型は nvarchar(32) で、既定値はありません。 Shared、Update、IntentShared、IntentExclusive、Exclusive のいずれかの値を指定できます。[ @LockOwner= ] 'lock_owner'
ロックの所有者を指定します。これはロックが要求されたときの lock_owner の値です。 lock_owner のデータ型は nvarchar(32) です。 指定できる値は、Transaction (既定値) または Session です。 lock_owner の値が既定により、または明示的に Transaction に指定されている場合、sp_getapplock はトランザクション内から実行する必要があります。[ @LockTimeout= ] 'value'
ロック タイムアウト値をミリ秒単位で指定します。 既定値は、@@LOCK_TIMEOUT で返される値と同じです。 ロック要求がすぐに許可されない場合に、ロックを待機するのではなくエラーを返すようにするには、0 を指定します。[ @DbPrincipal= ] 'database_principal'
データベース内のオブジェクトに対する権限を持つユーザー、ロール、またはアプリケーション ロールを指定します。 この関数を呼び出すには、database_principal、dbo、または固定データベース ロール db_owner のメンバーである必要があります。 既定値は public です。
戻り値
0 以上 (>= 0) の値 (成功) または 0 未満 (< 0) の値 (失敗)
値 |
結果 |
---|---|
0 |
ロックが同時に許可されました。 |
1 |
互換性のない他のロックが解放されるのを待機してから、ロックが許可されました。 |
-1 |
ロック要求がタイムアウトしました。 |
-2 |
ロック要求が取り消されました。 |
-3 |
ロック要求がデッドロックの対象になりました。 |
-999 |
パラメーターの検証エラーまたはその他の呼び出しエラー。 |
説明
リソースに設定されたロックは、現在のトランザクションまたは現在のセッションのいずれかに関連付けられます。 現在のトランザクションに関連付けられたロックは、トランザクションがコミットまたはロールバックされるときに解放されます。 セッションに関連付けられたロックは、セッションがログアウトされるときに解放されます。 サーバーがシャットダウンすると、すべてのロックは解放されます。
sp_getapplock によって作成されるロック リソースは、セッションの現在のデータベースで作成されます。 各ロック リソースは次の値の組み合わせで識別されます。
ロック リソースを含むデータベースのデータベース ID
@DbPrincipal パラメーターで指定されるデータベース プリンシパル
@Resource パラメーターで指定されるロック名
@DbPrincipal パラメーターで指定されるデータベース プリンシパルのメンバーだけが、そのプリンシパルを指定しているアプリケーション ロックを取得できます。 dbo ロールと db_owner ロールのメンバーは、暗黙的にすべてのロールのメンバーと見なされます。
ロックは、sp_releaseapplock で明示的に解放できます。 アプリケーションで、同じロック リソースに対して sp_getapplock が複数回呼び出される場合は、同じ回数だけ sp_releaseapplock を呼び出して、ロックを解放する必要があります。
sp_getapplock が同じロック リソースに対して複数回呼び出されても、その要求で指定されるロック モードが既存のモードと異なる場合、リソースでは 2 つのロック モードが混在することになります。 このため、ロック モードは多くの場合、既存のモードと新しく要求されたモードのうち、より強力なモードに昇格します。 この強力なロック モードは、その時点より前にロックの解放呼び出しが行われた場合でも、ロックが最終的に解放されるまで保持されます。 たとえば、次の一連の呼び出しの例において、リソースは Shared モードではなく Exclusive モードで保持されます。
USE AdventureWorks2012;
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 AdventureWorks2012;
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 Profiler を使ってロックを監視してください。
権限
public ロールのメンバーシップが必要です。
使用例
次の例では、現在のトランザクションに関連付けられている共有ロックを、AdventureWorks2012 データベースのリソース Form1 に設定します。
USE AdventureWorks2012;
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 = 'AdventureWorks2012',
@LockMode = 'Shared';
COMMIT TRAN;
GO