zoukankan      html  css  js  c++  java
  • 使用sp_getAppLock引发的一个小问题

    这几天线上频繁报如下的错误:“无法释放应用程序锁(数据库主体: 'public',资源: 'aa'),原因是当前没有保留该应用程序锁。”

    下面是写法:

     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是其他值或者加锁失败,会不会导致问题的发生,于是尝试了一下(手动滑稽)

    结果还真是,如果资源没申请成功会导致下面的报错。 下面为测试代码:

     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。

    参考链接:

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

    官网提供的例子是可以>=0 为成功,<0为失败。

    而代码例子的结构和我贴的结构几乎一致,所以开发人员当时应该是直接copy写法以后,然后就用了,完全没想到有什么其他的坑;→_→

    总结

    解决问题的过程很简单也很容易,但能够发现就是一个好事,侧面说明了看文档的重要性。

     -----追加

    验证资源锁是否存在

     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
  • 相关阅读:
    洛谷P1072 Hankson 的趣味题(题解)
    18.3.19晚听韩明睿大佬讲题收获
    题解+新技巧--一本通1282:最大子矩阵
    题解-洛谷P1303 A*B Problem(高精)
    Java重载和覆盖
    propagation属性的7个传播行为
    脏读、不可重复读、幻读
    RSA 数据加密和数字签名算法
    大型互联网站解决高并发的常见策略
    死锁和活锁
  • 原文地址:https://www.cnblogs.com/blog-east/p/11633856.html
Copyright © 2011-2022 走看看