使用sp_getAppLock引起的一個小問題

這幾天線上頻繁報以下的錯誤:「沒法釋放應用程序鎖(數據庫主體: 'public',資源: 'aa'),緣由是當前沒有保留該應用程序鎖。」sql

 

下面是寫法:數據庫

 1 declare @result int;
 2             BEGIN TRANSACTION
 3                 EXEC @result= sp_getapplock @Resource = N'aa',@LockMode = 'Exclusive',@LockTimeout=5000; 
 4                 if @result=-3
 5                 BEGIN
 6                     ROLLBACK TRANSACTION;
 7                 END
 8                 ELSE 
 9                 BEGIN
10                 select @result;
11                 EXEC SP_EXECUTESQL N'update xxx set f_date=f_date'
12                 EXEC sp_releaseapplock @Resource = N'aa';
13             COMMIT TRANSACTION
14             
15             END

 

看代碼第一反應可以發現,若是@result是其餘值或者加鎖失敗,會不會致使問題的發生,因而嘗試了一下(手動滑稽)app

結果還真是,若是資源沒申請成功會致使下面的報錯。 下面爲測試代碼:測試

 1 declare @result int;
 2             BEGIN TRANSACTION
 3                 --EXEC @result= sp_getapplock @Resource = N'aa',@LockMode = 'Exclusive',@LockTimeout=5000; 
 4                 --if @result=-3
 5                 --BEGIN
 6                 --    ROLLBACK TRANSACTION;
 7                 --END
 8                 --ELSE 
 9                 BEGIN
10                 select @result;
11                 EXEC SP_EXECUTESQL N'update xxx set f_date=f_date'
12                 EXEC sp_releaseapplock @Resource = N'aa';
13             COMMIT TRANSACTION
14             
15             END

 

因此上面的問題,能夠記錄下@rsult值是其餘的狀況下,是否也須要進行rollback。spa

 

參考連接:code

https://docs.microsoft.com/zh-cn/sql/relational-databases/system-stored-procedures/sp-getapplock-transact-sql?view=sql-server-2017server

 

官網提供的例子是能夠>=0 爲成功,<0爲失敗。blog

而代碼例子的結構和我貼的結構幾乎一致,因此開發人員當時應該是直接copy寫法之後,而後就用了,徹底沒想到有什麼其餘的坑;→_→ip

 

總結資源

解決問題的過程很簡單也很容易,但可以發現就是一個好事,側面說明了看文檔的重要性。

 -----追加

驗證資源鎖是否存在

 1 declare @resource nvarchar(255) ='aa' --資源字符串
 2 declare @key nvarchar(257)='['+@resource+']';
 3 IF exists(
 4 select 1 from   sys.dm_tran_locks 
 5 where 
 6     resource_type=N'APPLICATION' 
 7     AND request_mode=N'X' 
 8     and CHARINDEX(@key,resource_description) >0 
 9     and resource_database_id=db_id()
10 )
11 begin 
12     print ('已存在');
13 end
14 else 
15     begin
16         print ('不存在');
17     end
相關文章
相關標籤/搜索