这几天线上频繁报以下的错误:“没法释放应用程序锁(数据库主体: '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