我正在以下列方式使用TransactionScope
using (var scope = new TransactionScope())
{
using (var conn = SQLHelpers.GetSQLConnection())
{
//commands here
}
scope.Complete();
}
有时我在调用TransactionAbortedException
时收到scope.Complete()
,因为事务已经回滚,我使用了探查器来确定问题是死锁。
异常事务(进程ID 59)在锁资源上与另一个进程发生死锁,并被选为死锁牺牲品。重新运行该交易。
我发现了死锁的原因但是它让我想知道为什么这个错误没有冒出TransactionAbortedException
所以我确实可以为这个特定情况重新运行该事务。 内部异常不包含任何可以指示实际错误的信息。
检测TransactionAbortedException
是重新运行交易的原因是否安全?
到目前为止,我已经看到了以下内部异常:
1)死锁
2)超时
3)'连接已关闭'
4)..其他?
在其中只有一种情况下,重新运行事务似乎是合适的,但是如果保证回滚,可以将其推广到所有情况。可以重新提出这个问题来询问“TransactionAbortedException”是否保证交易被回滚' ?
答案 0 :(得分:3)
可以重新提出问题,问'做了吗? TransactionAbortedException保证事务已滚动 回'
TransactionAbortedException
的文档说:
尝试对事务执行操作时抛出此异常 已经回滚,例如,当您尝试时 在已超时的事务上调用
Commit
方法。 尝试提交时也会抛出此异常 交易和交易中止。这是一个可恢复的错误。
我认为从这个描述中可以清楚地看出,如果你发现这个例外,由于某种原因你的交易没有成功完成。我对文档的理解是:“无论交易尝试做什么改变都没有提交给数据库”。
“这是一个可恢复的错误”,因此如果您的事务的性质使得重试它是有意义的,那么您应该在捕获此异常后重试它。
您可能希望在重试时引入一些逻辑,例如在重试之前等待一段时间。并且随着重试次数的增加而增加此等待时间。对所有重试次数或总重试次数进行限制,并在所有重试尝试都失败时,做一些合理/失败的事情。
答案 1 :(得分:0)
这个问题来了,但是我正在研究类似的问题。
您需要考虑几件事
如果重新运行内部事务,则外部范围事务的状态 可能已经受到威胁。相当容易测试。
创建嵌套事务,
在调试期间内部事务停止。
转到sql server并运行一些查询以锁定内部事务使用的表。
运行内部事务并等待死锁。
在收到TransactionAboted异常后,返回sql server并释放锁。
环回并重新运行内部事务。
检查内部交易状态。
在尝试提交外部事务之前检查外部事务的状态。