using (var scope = new TransactionScope()) { using (var conn = sqlHelpers.GetsqlConnection()) { //commands here } scope.Complete(); }
有时我在调用scope.Complete()时收到TransactionAbortedException,因为事务已经回滚,我使用了探查器来确定问题是死锁.
Exception Transaction (Process ID 59) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
我已经找到了死锁的原因但是它让我想知道为什么这个错误没有冒泡到TransactionAbortedException所以我确实可以为这个特定情况重新运行事务.内部异常不包含任何可以指示实际错误的信息.
检测TransactionAbortedException作为重新运行事务的原因是否安全?
到目前为止,我已经看到以下内部异常:
1)死锁
2)超时
3)’连接已关闭’
4)..其他?
在其中只有一种情况下,重新运行事务似乎是合适的,但如果保证回滚,可以将其推广到所有情况.可以重新提出这个问题来询问’TransactionAbortedException是否保证交易被回滚’?
解决方法
The question could be re-stated to ask ‘does a
TransactionAbortedException guarantee the transaction was rolled
back’?
TransactionAbortedException
的文档说:
This exception is thrown when an action is attempted on a transaction
that has already been rolled back,for example,when you attempt to
call theCommit
method on a transaction that has already timed out.
This exception is also thrown when an attempt is made to commit the
transaction and the transaction aborts.This is a recoverable error.
我认为从这个描述中可以清楚地看出,如果你发现这个例外,由于某种原因你的交易没有成功完成.我对文档的理解是:“无论交易尝试做什么改变都没有提交给数据库”.
“这是一个可恢复的错误”,因此,如果您的事务的性质使得重试它是有意义的,那么您应该在捕获此异常后重试它.
您可能希望在重试时引入一些逻辑,例如在重试之前等待一段时间.并且随着重试次数的增加而增加此等待时间.限制总重试次数或总重试次数,并在所有重试尝试失败时优雅地执行某些操作.