使用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
相关文章
相关标签/搜索