hpk*_*k89 5 sql-server locking
昨天我们遇到了一个关键问题,其中一个 1 秒的存储过程开始需要几分钟才能执行。我目前还不知道业务逻辑,但是想了解使用sp_GetAppLock
.
所以场景是:
调用存储过程usp_abc
,无参数
存储过程中的代码如下所示:
BEGIN
BEGIN TRANSACTION
sp_getapplock @Resource = usp_abc, @LockMode = 'Exclusive'
with cte_1
( SELECT TOP 1 ID FROM tbl1 WHERE Status = 'OK')
UPDATE tbl1
SET Status = 'Complete'
WHERE ID = (SELECT ID FROM cte_1)
COMMIT TRAN
END
Run Code Online (Sandbox Code Playgroud)
这个存储过程是从同一个应用程序调用的,但是在来自两个不同应用程序服务器的负载平衡器上。存储过程不断执行,昨天因为积压,我们遇到了更多问题(每秒多次)。
我昨天在查询 sp_who2 时看到的是存储过程的执行被较早的执行阻止了。大约有 5 个 SPID 在做同样的事情。我追溯了第一个 SPID 以查看资源等待。它在SOS_SCHEDULER_YIELD
和 APPLICATION:5.0 " usp_abc
"之间波动- 基本上是它本身。
看起来它自己陷入了一个令人讨厌的循环,但有时执行确实完成了。在没有锁定的情况下自行运行更新时,它按预期运行亚秒。
一旦负载平衡器关闭并且请求来自单一来源,问题就在查询中消失了。
这不是我们的代码,但是我们想就如何阻止这种情况再次发生提出建议。据我所知,开发人员出于并发原因并可能避免死锁而将其设置到位。
然而,根据代码判断,在这种情况下,本机 sql 读取提交应该就足够了,因为它应该锁定正在更新的数据,这意味着不可能两次更新同一条记录。我认为这个查询不会出现死锁问题。
你怎么看?
尝试添加SET_XACT_ABORT ON
到存储过程以确保事务在因注意请求而终止后回滚。这是具有显式事务的过程的最佳实践。
可能导致您描述的症状的一种情况是,由于表阻塞,proc 执行在执行过程中超时。当客户端超时发生时,客户端 API 通过发送注意事件停止执行来取消 proc。这将取消正在执行的过程,但如果 不回滚事务SET_XACT_ABORT OFF
。事务将保持打开状态,直到连接关闭并重用(在连接池的情况下)、连接物理关闭或在同一连接上发出显式回滚或提交。
这对于在异常之后没有正确清理的持久(非池化)连接尤其令人讨厌,因为在连接上执行的所有后续工作都是在打开事务的上下文中不知不觉地完成的。
归档时间: |
|
查看次数: |
2413 次 |
最近记录: |