(SQL 服务器 2008) 如果在 TransactionScope (.Complete()) 中发生事务超时错误,您是否希望事务回滚?
更新:
错误实际上是在右大括号中抛出的(即 .Dispose()),而不是 .Complete()。完整错误是:
The transaction has aborted. System.Transactions.TransactionAbortedException TransactionAbortedException System.Transactions.TransactionAbortedException: The transaction has aborted. ---> System.TimeoutException: Transaction Timeout
--- End of inner exception stack trace ---
at System.Transactions.TransactionStateAborted.BeginCommit(InternalTransaction tx, Boolean asyncCommit, AsyncCallback asyncCallback, Object asyncState)
at System.Transactions.CommittableTransaction.Commit()
at System.Transactions.TransactionScope.InternalDispose()
at System.Transactions.TransactionScope.Dispose()
据我所知,事务没有回滚并且表一直处于锁定状态,直到我对 SPID/session_id 发出 KILL。
我使用 DBCC OPENTRAN 获取最早的事务,然后将其杀死。 我已尝试使用 KILL WITH STATUS 但收到一条消息,指出没有任何状态可用,因为没有任何内容被回滚。 sys.dm_exec_sessions 中 SPID/session_id 的状态是“ sleep ”。代码片段:
try
{
using (var transaction = new TransactionScope())
{
LOTS OF WORK CARRIED OUT WITH LINQ ENTITIES/SubmitChanges() etc.
transaction.Complete(); //Transaction timeout
}
return result;
}
catch (Exception ex)
{
logger.ErrorException(ex.Message, ex);
result.Fail(ex.Message);
return result;
}
更新:
问题并未完全解决,但如果其他人遇到此问题,请提供更多信息。
- 我正在使用 LINQ to SQL 并在事务范围内调用 context.SubmitChanges()。我正在执行大量插入操作。 SQL Server 事件探查器指示为每个插入发出一个单独的 INSERT 语句。
- 在开发中,如果我在调用 SubmitChanges() 之前让线程休眠 60 秒(默认 TransactionScope 超时为 60 秒),那么在调用 TransactionScope.Complete() 时我会得到一个不同的错误(该操作对状态无效交易。)。
- 如果我在 .SubmitChages() 之后和 .Complete() 之前睡了 60 秒,那么我得到 '事务已中止 - System.TimeoutException:事务超时'
- 但是请注意,在我的开发机器上,使用 DBCC opentran 时未发现打开的事务 - 这是您所期望的,因为您期望事务回滚。
- 如果我随后将此问题底部的代码(抱歉无法让网站将其插入此处)添加到我的配置文件中,这将 TransactionScope 超时增加到 2 分钟,事情将再次开始工作(研究表明如果这不起作用,machine.config 中可能有一个低于此优先级的设置)。
- 虽然这将阻止事务中止,但由于更新的性质,这确实意味着锁定核心业务表可能长达 2 分钟,因此使用默认 SqlCommand 超时 30 秒的其他选择命令将超时。不理想,但总比坐在那里并完全阻止应用程序的公开交易要好。
- 几天前,我们发布了一个灾难性版本,这意味着我们在升级过程中用完了磁盘空间 (!),因此我们最终使用了收缩数据库功能,这显然会在您使用后导致性能问题。
我感觉要重建数据库并重新考虑一些业务功能......
最佳答案
我认为 TransactionAbortedException 实际上是一个超时。如果是这样,您应该会发现 TransactionAbortedException 的 InnerException 是超时。
您应该能够通过确保事务作用域的超时时间长于命令超时时间来摆脱它。
尝试将事务范围更改为如下内容:
new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(60))
并且还在您的上下文中设置一个明确的超时。应该是这样的:
myContext.CommandTimeout = 30; //This is seconds
关于c# - TransactionScope TransactionAborted 异常 - 事务未回滚。应该吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7006806/