【发布时间】:2017-03-31 12:17:37
【问题描述】:
使用 ADO.NET SqlClient 类时,有几种方法可以回滚事务。通过显式调用SqlTransaction.Rollback,或具有命令超时,或事务范围内的事务超时等。
但是,在使用 SQL Server(2012 或更高版本)时,如何检测此回滚何时完成?对于长时间运行的事务,回滚可能需要很长时间,并且通常在数据库上相当 IO 密集,因此立即重试事务可能不明智。在我们的情况下,我们希望等待回滚完成。
(在我们的特定情况下,由于使用 TransactionScope 类的事务超时而发生回滚,但我更喜欢适用于任何类型回滚的方法)。
我看过sys.dm_exec_requests,起初看起来很有希望。它最初的命令类型为KILL/ROLLBACK,并报告了进度百分比。 (如果我从原始事务中捕获 SPID,我将能够轮询该表并等待它完成)。然而,大约在进行到一半时,我注意到它改为AWAITING COMMAND(而回滚仍在执行中)。
我还看了KILL <SPID> WITH STATUSONLY。如果没有正在进行的回滚,这似乎会产生错误,因此它也可以用于轮询方法,但我注意到如果我从 SSMS 运行 BEGIN TRAN ... ROLLBACK TRAN 批处理,则会报告一个错误,指出没有回滚回滚时的进度。在这种情况下,dm_exec_requests 表将 ROLLBACK TRANSACTION 报告为命令类型。
那么如何才能以可靠的方式等待回滚完成呢?
【问题讨论】:
-
因为在这种情况下,回滚期间 SQL 服务器上的负载太高,甚至无法尝试重新运行事务。所以我们希望等到回滚完成并且数据库服务器有更多资源可用于执行下一个实际事务。
-
抱歉,我删除了我的评论,因为我在我的问题中找到了答案。我在问“如果您在 READ_COMMITED 中,您的代码不应读取未提交的数据,为什么还要打扰?”同样在 .NET 中,您的请求将在此选项中等待您的事务完成。
-
类似的问题,虽然措辞不同。您似乎想等到当前事务提交或回滚后再尝试另一个事务。 stackoverflow.com/questions/18457955/…
-
@WilliamXifaras 这个问题似乎主要涉及事务之间的锁定。如果我的交易因任何原因中止,例如。
SqlCommand.ExecuteNonQuery事务超时10分钟后抛出异常,我想等待数据库完成回滚。 -
如果是时间/性能问题,也许你应该把你的工作分解成更小的单元。就查询状态而言,sys.dm_exec_requests 似乎是您最好的选择。
标签: .net sql-server transactions