次の方法で共有


sys.sp_getapplock (Transact-SQL)

Applies to:SQL ServerAzure SQL Database< Microsoft FabricAzure SQL Managed InstanceSQL データベース>

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

Transact-SQL 構文規則

構文

sys.sp_getapplock
    [ [ @Resource = ] N'Resource' ]
    , [ @LockMode = ] 'LockMode'
    [ , [ @LockOwner = ] 'LockOwner' ]
    [ , [ @LockTimeout = ] LockTimeout ]
    [ , [ @DbPrincipal = ] N'DbPrincipal' ]
[ ; ]

引数

[ = ] N'Resource'

ロック リソースを識別する名前を指定する文字列。 @Resource は nvarchar(255) で、既定値は です。 リソース文字列が nvarchar(255) より長い場合、値は nvarchar(255)に切り捨てられます。

アプリケーション側では、リソース名が一意になるよう管理されている必要があります。 指定された名前は、SQL Server ロック マネージャーに格納できる値に内部的にハッシュされます。

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

Note

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

[ = ] 『ロックモード』

特定のリソースに対して取得されるロック モード。 @LockMode は varchar(32)であり、既定値はなく、次のいずれかの値です。

  • Shared
  • Update
  • IntentShared
  • IntentExclusive
  • Exclusive

詳細については、「 ロック モード」を参照してください。

[ = ] 「ロックオーナー」

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

[ = ] ロックタイムアウト

ロック タイムアウト値 (ミリ秒)。 @LockTimeout は int であり、既定値は によって返される値と同じです。 値 (既定値) は、タイムアウト期間がないことを示します (つまり、永久に待機します)。 ロック要求がすぐに許可できないときにロックを待機するのではなく、 のリターン コードを返す必要があることを示すには、 を指定します。

[ = ] N'Db校長

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

リターン コードの値

(成功)、または (失敗)。

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

解説

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

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

  • ロック リソースを含むデータベースのデータベース ID。
  • @DbPrincipal パラメーターで指定されたデータベース プリンシパル。
  • パラメーターで指定されたロック名。

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

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

が同じロック リソースに対して複数回呼び出されるが、いずれかの要求で指定されたロック モードが既存のモードと同じでない場合、リソースへの影響は 2 つのロック モードの和集合になります。 ほとんどの場合、ロック モードは、ロック モード、既存のモード、または新しく要求されたモードのより強力なモードに昇格されます。 このより強力なロック モードは、ロック解放呼び出しがその時刻より前に発生した場合でも、ロックが最終的に解放されるまで保持されます。

たとえば、次の一連の呼び出しでは、リソースは モードではなく モードで保持されます。

USE AdventureWorks2025;
GO

BEGIN TRANSACTION;

DECLARE @result AS INT;

EXECUTE
    @result = sp_getapplock
    @Resource = 'Form1',
    @LockMode = 'Shared';

EXECUTE
    @result = sp_getapplock
    @Resource = 'Form1',
    @LockMode = 'Exclusive';

EXECUTE
    @result = sp_releaseapplock
    @Resource = 'Form1';

COMMIT TRANSACTION;
GO

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

次に例を示します。

USE AdventureWorks2025;
GO

BEGIN TRANSACTION;

DECLARE @result AS INT;

EXECUTE
    @result = sp_getapplock
    @Resource = 'Form1',
    @LockMode = 'Exclusive';

IF @result = -3
BEGIN
    ROLLBACK;
END
ELSE
BEGIN
    EXECUTE
        @result = sp_releaseapplock
        @Resource = 'Form1';
    COMMIT TRANSACTION;
END
GO

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

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

アクセス許可

パブリック固定データベース ロールのメンバーシップが必要です。

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

USE AdventureWorks2025;
GO

BEGIN TRANSACTION;

DECLARE @result AS INT;

EXECUTE
    @result = sp_getapplock
    @Resource = 'Form1',
    @LockMode = 'Shared';

COMMIT TRANSACTION;
GO

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

BEGIN TRANSACTION;

EXECUTE sp_getapplock
    @DbPrincipal = 'dbo',
    @Resource = 'AdventureWorks2025',
    @LockMode = 'Shared';

COMMIT TRANSACTION;
GO