這幾天線上頻繁報以下的錯誤:「沒法釋放應用程序鎖(數據庫主體: '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
官網提供的例子是能夠>=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