如何查找停滞sp_getapplock调用对应的resource_name
sys.dm_tran_locks不会直接明文存储应用锁的resource_name,仅存储锁的哈希标识,可通过系统兼容视图sys.syslockinfo直接关联获取明文资源名称,操作步骤如下:
关联查询锁与对应resource_name
sys.syslockinfo是SQL Server全版本支持的向后兼容系统视图,其中应用锁类型(rsc_type=7,对应sys.dm_tran_locks的resource_type='APPLICATION')条目的rsc_text字段,直接存储了调用sp_getapplock时传入的原始resource_name明文。
使用以下查询可直接获取所有应用锁的全量信息,你可以在语句中追加自定义过滤条件,筛选出你识别到的停滞异常锁:
SELECT tl.request_session_id, DB_NAME(tl.resource_database_id) AS belong_db, sli.rsc_text AS applock_resource_name, tl.request_mode, tl.request_status, tl.request_owner_type, tl.request_owner_id AS belong_transaction_id FROM sys.dm_tran_locks tl INNER JOIN sys.syslockinfo sli ON tl.lock_owner_address = sli.req_owner_address WHERE tl.resource_type = 'APPLICATION' AND sli.rsc_type = 7 -- 可追加自定义过滤条件,例如: -- AND DB_NAME(tl.resource_database_id) = '你的业务库名' -- AND tl.request_status = 'GRANT' -- 筛选无活跃请求的休眠会话持有的锁 -- AND NOT EXISTS (SELECT 1 FROM sys.dm_exec_requests er WHERE er.session_id = tl.request_session_id)
释放异常锁的注意事项
拿到resource_name后调用sp_releaseapplock时,必须和原加锁逻辑的上下文保持一致,否则会释放失败:
- 执行
sp_releaseapplock前必须切换到加锁时所在的业务数据库上下文,和原sp_getapplock调用的数据库保持一致。 @LockOwner参数必须和加锁时传入值一致:默认值为Transaction(事务级锁),这类锁会随事务提交/回滚自动释放,长期滞留的异常锁基本都是会话级锁,对应参数值为Session。@DbPrincipal参数必须和加锁时传入的数据库主体一致,未显式指定时默认值为public。
注意:仅对已经确认是异常停滞、确实造成业务阻塞的锁执行释放操作,禁止在业务高峰无差别批量释放应用锁,避免干扰正常业务的锁校验逻辑。
备选方案(不推荐)
如果你的环境因安全限制无法使用sys.syslockinfo视图,可以尝试通过sys.dm_exec_connections的most_recent_sql_handle字段,拿到持有锁会话最后一次执行的SQL文本,从中解析sp_getapplock传入的resource_name。但该方法局限性极强:如果会话执行完sp_getapplock后又运行了其他SQL语句,最近SQL句柄会被覆盖,无法获取原始参数,仅作为极端场景下的备选。
内容的提问来源于stack exchange,提问作者Robert Sievers

