TransactionScope TransactionAborted Exception - транзакция не откатна. Должно быть?
(SQL SERVER 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()
Насколько я могу судить, транзакция не откатывается назад, а таблицы остаются заблокированными, пока я не выдал KILL против SPID/session_id.
Я использовал DBCC OPENTRAN для получения самой старой транзакции, а затем KILL.
Я попробовал KILL WITH STATUS, но получил сообщение о том, что статус не доступен, поскольку ничто не откатывается назад. Состояние SPID/session_id в sys.dm_exec_sessions является "спящим". Фрагмент кода:
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;
}
UPDATE:
Проблема не полностью решена, но дополнительная информация должна быть у кого-либо еще.
Ответы
Ответ 1
Я думаю, что TransactionAbortedException на самом деле является таймаутом. Если это так, вы должны обнаружить, что InnerException для TransactionAbortedException является таймаутом.
Вы должны быть в состоянии избавиться от него, убедившись, что таймаут транзакции длиннее тайм-аута команды.
Попробуйте изменить область транзакций на что-то вроде этого:
new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(60))
А также установите явный тайм-аут в вашем контексте. Должно быть что-то вроде:
myContext.CommandTimeout = 30; //This is seconds
Ответ 2
Я разрешаю эту проблему, изменяя "физический файл" machine.config.
1. Вы должны локализовать файл:
- 32 бита: C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machie.config
- 64 бита: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config
2. Вам нужно добавить следующий код:
<system.transactions>
<defaultSettings timeout="00:59:00" />
</system.transactions>