TransactionScope TransactionAborted Exception - транзакция не откатывается. Должно ли это быть? - PullRequest
15 голосов
/ 10 августа 2011

(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, чтобы получить самую старую транзакцию, а затем УБИТЬ ее. Я попытался УБИТЬ С СОСТОЯНИЕМ, но получил сообщение, что статус недоступен, так как ничего не откатывается. Состояние 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. Я использую LINQ to SQL, и в рамках транзакции я вызываю context.SubmitChanges (). Я выполняю много вставок. Профилировщик SQL Server указывает, что для каждой вставки выдается отдельный оператор INSERT.
  2. В процессе разработки, если я сплю поток в течение 60 секунд (время ожидания TransactionScope по умолчанию составляет 60 секунд) ПЕРЕД вызовом SubmitChanges (), я получаю другую ошибку при вызове TransactionScope.Complete () (операция недопустима для состояния сделка.).
  3. Если я сплю 60 секунд ПОСЛЕ .SubmitChages () и непосредственно перед .Complete (), я получаю 'Транзакция прервана - System.TimeoutException: время ожидания транзакции'
  4. ОБРАТИТЕ ВНИМАНИЕ, однако, что на моем компьютере разработчика не обнаружены открытые транзакции при использовании DBCC opentran - это то, что вы ожидаете, так как ожидаете отката транзакции.
  5. Если я затем добавлю код в нижней части этого вопроса (извините, я не смог заставить сайт вставить его здесь) в мой файл конфигурации, который увеличивает тайм-аут TransactionScope до 2 минут, все снова начинает работать (исследования показывают, что если это не работает, в machine.config может быть параметр, который ниже, чем тот, который имеет приоритет).
  6. Хотя это остановит прерывание транзакции, из-за характера обновлений это означает, что блокировки основной бизнес-таблицы могут длиться до 2 минут, поэтому другие команды выбора, использующие тайм-аут SqlCommand по умолчанию, равный 30 секундам, будут иметь тайм-аут. Не идеально, но лучше, чем открытая транзакция, сидящая там и полностью удерживающая приложение.
  7. Несколько дней назад у нас был катастрофический выпуск, который означал, что у нас закончилось дисковое пространство в середине обновления (!), Поэтому мы в конечном итоге использовали функциональность сжатой базы данных, которая, очевидно, может вызвать проблемы с производительностью после ее использования.
  8. Я чувствую перестройку базы данных и переосмысление некоторых бизнес-функций ...

Ответы [ 2 ]

14 голосов
/ 11 августа 2011

Я думаю, что TransactionAbortedException на самом деле является тайм-аутом.Если это так, вы должны обнаружить, что InnerException TransactionAbortedException является тайм-аутом.

Вы должны быть в состоянии избавиться от него, убедившись, что тайм-аут транзакции больше, чем тайм-аут команды.

Попробуйте изменить область транзакции на что-то вроде этого:

new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(60))

А также установите явный тайм-аут в своем контексте.Должно быть что-то вроде:

myContext.CommandTimeout = 30; //This is seconds
0 голосов
/ 01 июля 2016

Я решаю эту проблему, изменяя « физический файл » 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>
...