我们已经使用一种机制(一个名为SqlDeadlockHelper
的类)很长一段时间了,在尝试由于死锁而失败的数据库调用时,它对我们有很大帮助。SqlDeadlockHelper
将捕获一个SqlException
,识别出它是死锁,然后重试。第二次尝试几乎总是成功的。
对于命令和/或连接超时,这样做安全吗?我的意思是,在SQL Server上完成工作是不可能的,只是在数据返回到调用者之前超时,是吗?
编辑:
事务被认为是将调用视为一个工作单元的一种方式。这样它就可以成功或完全回滚。但是,一个ADO.NET调用只做一件事呢。有必要将其封装在事务中吗?
根据您的工作单元,SQL有可能在死锁并引发错误之前完成部分工作。处理工作单元的方式是使用事务。大多数SQL数据库都支持事务。您需要将工作单元包装在Begin、Commit和Rollback事务中。
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqltransaction.aspx
来自TechNet库
检测到死锁后,数据库引擎通过选择其中一个线程作为死锁牺牲品。数据库引擎终止正在为线程执行的当前批处理,回滚死锁受害者的事务,并向应用程序。回滚死锁受害者的事务释放事务所持有的所有锁。这允许其他线程的事务将被取消阻止并继续。1205死锁受害者错误记录有关线程的信息以及错误日志中死锁所涉及的资源。
因此,您的事务已安全回滚,您可以重试。
编辑
作为一个懒惰的人,我没有把你的问题读透。让我们看看:
对于命令和/或连接超时,这样做安全吗?
我不会做同样的概括,因为您最终可能会尝试从根本无法访问的数据库中读取数据。您应该有最大重试次数。
我的意思是,在SQL Server上不可能完成工作,只能在数据返回给调用者之前超时,是吗?
从未听说过,如果您使用事务,这应该是不可能的。您应该使用它们,以及XACT_ABORT,即Specifies whether SQL Server automatically rolls back the current transaction when a Transact-SQL statement raises a run-time error.
的标志。然而,工作可能既不完成也不完成——请参阅僵尸事务。
我刚刚也发现了这个。