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