Answers:
扩展Mark的答案...
发生客户端超时事件时(例如.net CommandTimeout),客户端将向SQL Server发送“ ABORT”。然后,SQL Server简单地放弃查询处理。没有事务回滚,没有锁释放。
现在,连接返回到连接池,因此在SQL Server上不会关闭。如果发生这种情况(通过KILL或客户端重新启动等),则将清除事务+锁。请注意,sp_reset_connection不会或不会清除它们,即使已进行了宣传
中止的这种破坏将阻止其他进程。
使SQL Server清除事务+客户端超时锁定(严格来说是ABORT事件)的方法是使用SET XACT_ABORT ON。
您可以验证是否正在SSMS中打开2个查询窗口:
视窗1:
在菜单Query..Query Options中,将超时设置为5秒,然后运行
BEGIN TRAN
UPDATE sometable WITH (TABLOCKX) SET foo = foo WHERE 1 = 0;
WAITFOR DELAY '00:00:10' -- just has to be longer then timeout
窗口2,这将永远等待(或超时)
SELECT * FROM sometable
SET XACT_ABORT ON也具有有趣的副作用:
这两者的结合意味着您不能对部分提交/回滚使用SAVEPOINTS(尽管我无法回忆起确切的行为)。哪个适合我
SET XACT_ABORT上的SO链接:
在嵌套的存储过程中:
在sp_reset_connection上:
我很犹豫地回答这个问题,因为在您对问题的描述中没有足够的信息可以百分百确定这是最好的建议。“挂断或引发异常”表明未正确理解问题的根源,因此请谨慎操作。
最简单的解决方案可能是SET XACT_ABORT ON
。
XACT_ABORT
确定在运行时错误的情况下SQL Server是否将回滚事务。默认值SET XACT_ABORT OFF
将仅回滚导致错误的语句,从而使所有父事务保持打开状态。
默认设置的“陷阱”副作用是超时可能导致完全相同的问题,这是客户负责处理和回滚的开放事务。如果客户不尝试/捕获/回滚,则该事务将一直保持打开状态,直到处理(我引用@gbn)的超暴力行为为止KILL <spid>
。
经常引用Erland Sommarskog关于SQL Server中的错误处理的文章,其中包含处理这些情况及更多信息所需的所有背景和策略。
编辑(以下注释):要识别未完成的事务,sp_whoisactive可能是功能最齐全的。