Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 TransactionScope и "escalation to DTC"  [new]
KellyLynch
Member

Откуда:
Сообщений: 94
У меня есть (достался в наследство) примерно такой код
(MS SQL 2008; .NET 4)

using (var tranScope = new TransactionScope())
{
    using (SqlConnection connection = new SqlConnection(connectionString)) {
      connection.Open();
	  ...
	  using (SqlConnection connection2 = new SqlConnection(connectionString)) {
               connection2.Open();
	       //...вызов моей процедуры MyStoredProc используя connection2
               connection2.Close();
          }
	
      connection.Close();
    }
}


Оказалось - вызов той процедуры MyStoredProc приводит к ошибке, если в ней используется "SAVE TRANSACTION". Ошибка такая: "Cannot use SAVE TRANSACTION within a distributed transaction."

Как я понял, проищошло вот что: когда открылось соединение connection2, этот внешний TransactionScope "escalate to DTC". Этот DTC - это Microsoft Distributed Transaction Coordinator. Мне он непосрелдственно не нужен; но как результат этого - транзакция внутри connection2 стала Distributed; и таким образом законфликтовала с "SAVE TRANSACTION".

Что можно сделать? Как я говорил, мне никакие Distributed Transactions на самом деле не нужны. TransactionScope введён был для того чтобы в самом конце всё откатить (код представляет собой UnitTest-ы, и им нужно откатывать изменения сделанные ими в базе). Как НЕ допустить этого "escalate to DTC"?
11 мар 14, 11:55    [15703212]     Ответить | Цитировать Сообщить модератору
 Re: TransactionScope и "escalation to DTC"  [new]
Glory
Member

Откуда:
Сообщений: 104751
KellyLynch
Как я понял, проищошло вот что: когда открылось соединение connection2, этот внешний TransactionScope "escalate to DTC".

Открытие коннекта никак не может изменить область уже имеющихся транзакций.
11 мар 14, 11:57    [15703242]     Ответить | Цитировать Сообщить модератору
 Re: TransactionScope и "escalation to DTC"  [new]
KellyLynch
Member

Откуда:
Сообщений: 94
Glory
KellyLynch
Как я понял, проищошло вот что: когда открылось соединение connection2, этот внешний TransactionScope "escalate to DTC".

Открытие коннекта никак не может изменить область уже имеющихся транзакций.


Похоже, я не вполне точно выразился. Точнее - некритично процитировал отсюда вот: http://stackoverflow.com/questions/1690892/transactionscope-automatically-escalating-to-msdtc-on-some-machines.

Под "escalate to DTC" имелось в виду:
в результате получится ситуация которую можно назвать escalation to DTC. А именно: внутренний connection2 (не transactionscope - Вы правы) будет " escalated to DTC". А "виновато" в этом наличие того TransactionScope.
11 мар 14, 12:32    [15703561]     Ответить | Цитировать Сообщить модератору
 Re: TransactionScope и "escalation to DTC"  [new]
Glory
Member

Откуда:
Сообщений: 104751
И причем тут собственно mssql сервер ?
11 мар 14, 12:36    [15703597]     Ответить | Цитировать Сообщить модератору
 Re: TransactionScope и "escalation to DTC"  [new]
Crimean
Member

Откуда:
Сообщений: 13147
а убирайте save tran-ы - это, обычно, наследие со времен, когда не было TRY, таким образом, обычно, давилось "любимое"

Server: Msg 266, Level 16, State 2, Procedure **, Line **
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0.

но с появлением TRY это уже не актуально. правда, THROW только с 12 работает, так что под 2008 есть риск потерять "номер" ошибки и это может быть критично, если номер важен дальше по цепочке..
11 мар 14, 12:49    [15703737]     Ответить | Цитировать Сообщить модератору
 Re: TransactionScope и "escalation to DTC"  [new]
KellyLynch
Member

Откуда:
Сообщений: 94
Crimean
а убирайте save tran-ы - это, обычно, наследие со времен, когда не было TRY, таким образом, обычно, давилось "любимое"

Server: Msg 266, Level 16, State 2, Procedure **, Line **
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0.

но с появлением TRY это уже не актуально. правда, THROW только с 12 работает, так что под 2008 есть риск потерять "номер" ошибки и это может быть критично, если номер важен дальше по цепочке..


>убирайте save tran-ы

хорошо бы. Но по некоторым причинам сейчас это сделать не получается....
И что - больше ничего нельзя предпринять?
11 мар 14, 14:03    [15704307]     Ответить | Цитировать Сообщить модератору
 Re: TransactionScope и "escalation to DTC"  [new]
Crimean
Member

Откуда:
Сообщений: 13147
KellyLynch,

распределенная транзакция всегда обламывается на первой же инструкции SAVE TRAN, увы
а необходимость в save (ИМХО!) - только давить "то самое" сообщение, реально я больше не могу вспомнить, для чего оно было бы "совсем-совсем" надо
конечно, откатывать до сейвпоинта иногда кажется "интересным", но, как правило, это не лучший способ построения обработки ошибок. и это уж точно выпадает из "мейнстрима" обработки ошибок по MS - у них принято "сворачиваться" при первом же исключении. ибо даже если вдруг вы сделаете TRY / CATCH и попытаетесь "спрятать" неважное для вас исключение - с неплохой вероятностью вы будете в этот момент уже в "non-committable state" (если правильно пишу термин, но смысл тот), откуда можно сделать только ROLLBACK и все, привет

так что код с сейвами не работал и не будет работать в распределенной транзакции - или убирайте или делайте их условными. но (имхо!) лучше убирайте вообще. а где мешают побочные эффекты - try / catch вам в помощь и ждите 2012 с его throw

правда, под 2008 можно частично заткнуть проблему недокументированным синтаксисом raiserror @no @msg, но он имеет ограничения по номерам ошибок. хотя мне местами он сильно помог сохранить номер ошибки при использовании try / catch
11 мар 14, 14:32    [15704562]     Ответить | Цитировать Сообщить модератору
 Re: TransactionScope и "escalation to DTC"  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Crimean,

Ок, SAVE POINT нафег.
Но зачем и TRY/CATCH ? Тоже в топку. Юзать старый добрый XACT_ABORT притом что THROW прерывает пакет в отличие от RAISERROR.
Хотя можно прервать пакет и без THROW.

Если вы говорите что иногда надо TRY/CATCH, то:
1. Пример в студию!
2. Почему это тогда никогда не надо SAVE POINT ?
Иногда легче "переключить" на альтернативное действие, чем всё откатывать и делать знуля.
(тут много можно спорить и все аргументы будут схоластикой в обе стороны)

Система может прерваться в любом месте TRY / CATCH на PowerOff не повесишь.

И да, убирать TRY / CATCH и SAVE POINT из скуля не надо. Это всё та же парадигма Enterprise.
11 мар 14, 23:53    [15707788]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить