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