分享方式:


sp_getapplock (Transact-SQL)

適用於: SQL Server Azure SQL 資料庫 Azure SQL 受控執行個體

將鎖定放在應用程式資源上。

Transact-SQL 語法慣例

語法

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

引數

[ @Resource = ] N'資源'

指定識別鎖定資源之名稱的字串。 @Resource為 nvarchar(255),預設值為 NULL。 如果資源字串超過 nvarchar(255),則會將值截斷為 nvarchar(255)。

應用程式必須確保資源名稱是唯一的。 指定的名稱會在內部哈希為可儲存在 SQL Server 鎖定管理員中的值。

@Resource會進行二進位比較,因此不論目前資料庫的定序設定為何,都會區分大小寫。

注意

取得應用程式鎖定之後,只能以純文字擷取前 32 個字元:其餘部分將會進行哈希處理。

[ @LockMode = ] 'LockMode'

要針對特定資源取得的鎖定模式。 @LockMode為 varchar(32),不含預設值,且為下列其中一個值:

  • Shared
  • Update
  • IntentShared
  • IntentExclusive
  • Exclusive

如需詳細資訊,請參閱 鎖定模式

[ @LockOwner = ] 'LockOwner'

鎖定的擁有者,這是 要求鎖定時@LockOwner 值。 @LockOwner為 varchar(32),預設值為 Transaction。 值也可以是 Session當@LockOwner值為 Transaction時,預設或明確指定時,sp_getapplock必須從交易內執行。

[ @LockTimeout = ] LockTimeout

鎖定逾時值,以毫秒為單位。 @LockTimeout 為 int,且預設值與 所@@LOCK_TIMEOUT回的值相同。 值 -1 (預設值) 表示沒有逾時期間 (也就是永遠等候)。 若要指出鎖定要求應該傳回 的 -1 傳回碼,而不是在無法立即授與要求時等候鎖定,請指定 0

[ @DbPrincipal = ] N'DbPrincipal'

具有資料庫中物件許可權的使用者、角色或應用程式角色。 @DbPrincipal為 sysname,預設值為 public。 函式的呼叫端必須是database_principal、dbodb_owner固定資料庫角色的成員,才能成功呼叫函式。 預設值為 public

傳回碼值

>= 0 (成功),或 < 0 (失敗)。

結果
0 鎖定已成功以同步方式授與。
1 等候其他不相容的鎖定釋出之後,已成功授與鎖定。
-1 鎖定要求逾時。
-2 鎖定要求已取消。
-3 鎖定要求已選擇為死結受害者。
-999 表示參數驗證或其他呼叫錯誤。

備註

資源上放置的鎖定會與目前交易或目前會話相關聯。 當交易認可或回復時,會釋放與目前交易相關聯的鎖定。 當會話註銷時,會釋放與會話相關聯的鎖定。當伺服器因任何原因關閉時,會釋放所有鎖定。

sp_getapplock 建立的鎖定資源會在會話的目前資料庫中建立。 每個鎖定資源都是透過下列組合值來識別:

  • 包含鎖定資源之資料庫的資料庫識別碼。
  • @DbPrincipal 參數中指定的資料庫主體。
  • 參數中指定的 @Resource 鎖定名稱。

只有@DbPrincipal參數中指定的資料庫主體成員可以取得指定該主體的應用程序鎖定。 dbodb_owner角色的成員會隱含地視為所有角色的成員。

您可以使用 明確釋放 sp_releaseapplock鎖定。 當應用程式 sp_getapplock 呼叫相同鎖定資源的多次時, sp_releaseapplock 必須呼叫相同次數才能釋放鎖定。 使用鎖定擁有者開啟 Transaction 鎖定時,交易認可或回復時就會釋放該鎖定。

如果 sp_getapplock 針對相同的鎖定資源呼叫多次,但是在任何要求中指定的鎖定模式與現有模式不同,則對資源的影響是兩種鎖定模式的聯集。 在大部分情況下,這表示鎖定模式會升階為鎖定模式、現有模式或新要求的模式。 即使鎖定釋放呼叫在該時間之前發生,這個更強的鎖定模式仍會保留,直到鎖定最終釋放為止。

例如,在下列一連串的呼叫中,資源會保留在模式中 Exclusive ,而不是在 模式中 Shared

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 會使用目前的資料庫標識碼來限定資源。 因此,如果 sp_getapplock 執行 ,即使在不同的資料庫上使用相同的參數值,結果也會是個別資源的個別鎖定。

sys.dm_tran_locks使用動態管理檢視或sp_lock系統預存程式來檢查鎖定資訊,或使用 SQL Server Profiler 監視鎖定。

權限

需要 public 角色的成員資格。

範例

下列範例會在資料庫中的資源上Form1AdventureWorks2022放置與目前交易相關聯的共享鎖定。

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