次の方法で共有


sp_getapplock (Transact-SQL)

適用対象: SQL Server Azure SQL Database Azure SQL Managed Instance

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

Transact-SQL 構文表記規則

構文

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

引数

[ @Resource = ] N'Resource'

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

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

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

Note

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

[ @LockMode = ] 'LockMode'

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

  • Shared
  • Update
  • IntentShared
  • IntentExclusive
  • Exclusive

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

[ @LockOwner = ] 'LockOwner'

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

[ @LockTimeout = ] LockTimeout

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

[ @DbPrincipal = ] N'DbPrincipal'

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

リターン コードの値

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

結果
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 TRANSACTION;

DECLARE @result INT;

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

COMMIT TRANSACTION;
GO

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

BEGIN TRANSACTION;

EXEC sp_getapplock
    @DbPrincipal = 'dbo',
    @Resource = 'AdventureWorks2022',
    @LockMode = 'Shared';

COMMIT TRANSACTION;
GO