Подтвердить что ты не робот

TransactionScope. Основной провайдер не удалось выполнить команду EnlistTransaction. MSDTC прерывается

У нашей команды есть проблема, которая проявляется как:

Недопустимый базовый провайдер в EnlistTransaction; Не удается получить доступ к Объект object.Object: 'Transaction'.

enter image description here

который, казалось, появился, как только мы начали использовать TransactionScope для обработки транзакций наших приложений.

Верхняя часть stacktrace фиксируется как:

в System.Data.EntityClient.EntityConnection.EnlistTransaction(транзакция Transaction) в System.Data.Objects.ObjectContext.EnsureConnection() в System.Data.Objects.ObjectContext.ExecuteStoreCommand(String CommandText, Object [] Параметры) в Reconciliation.Models.BillLines.BillLines.Reconciliation.Interfaces.IBillLineEntities.ExecuteStoreCommand(String, Object []) в Reconciliation.Models.Legacy.EntityDbEnvironment.ExecuteOracleSql(String SQL) в EntityDbEnvironment.cs: строка 41

В то же время обновляется журнал MSDTC, который я извлек с помощью здесь:

pid=7060       ;tid=7908       ;time=04/29/2013-16:38:30.269   ;seq=136        ;eventid=TRANSACTION_BEGUN                        ;tx_guid=60f6390c-7570-488a-97a9-2c3912c4ca3e     ;"TM Identifier='(null)                                            '" ;"transaction has begun, description :'<NULL>'"
pid=7060       ;tid=7908       ;time=04/29/2013-16:38:30.269   ;seq=137        ;eventid=RM_ENLISTED_IN_TRANSACTION               ;tx_guid=60f6390c-7570-488a-97a9-2c3912c4ca3e     ;"TM Identifier='(null)                                            '" ;"resource manager #1002 enlisted as transaction enlistment #1. RM guid = 'defc4277-47a6-4cd9-b092-93a668e2097b'"
pid=7060       ;tid=7908       ;time=04/29/2013-16:38:31.658   ;seq=138        ;eventid=RECEIVED_ABORT_REQUEST_FROM_BEGINNER     ;tx_guid=60f6390c-7570-488a-97a9-2c3912c4ca3e     ;"TM Identifier='(null)                                            '" ;"received request to abort the transaction from beginner"
pid=7060       ;tid=7908       ;time=04/29/2013-16:38:31.658   ;seq=139        ;eventid=TRANSACTION_ABORTING                     ;tx_guid=60f6390c-7570-488a-97a9-2c3912c4ca3e     ;"TM Identifier='(null)                                            '" ;"transaction is aborting"
pid=7060       ;tid=7908       ;time=04/29/2013-16:38:31.658   ;seq=140        ;eventid=RM_ISSUED_ABORT                          ;tx_guid=60f6390c-7570-488a-97a9-2c3912c4ca3e     ;"TM Identifier='(null)                                            '" ;"abort request issued to resource manager #1002 for transaction enlistment #1"
pid=7060       ;tid=7908       ;time=04/29/2013-16:38:31.658   ;seq=141        ;eventid=RM_ACKNOWLEDGED_ABORT                    ;tx_guid=60f6390c-7570-488a-97a9-2c3912c4ca3e     ;"TM Identifier='(null)                                            '" ;"received acknowledgement of abort request from the resource manager #1002 for transaction enlistment #1"
pid=7060       ;tid=7908       ;time=04/29/2013-16:38:31.658   ;seq=142        ;eventid=TRANSACTION_ABORTED                      ;tx_guid=60f6390c-7570-488a-97a9-2c3912c4ca3e     ;"TM Identifier='(null)                                            '" ;"transaction has been aborted"

Как вы видите RECEIVED_ABORT_REQUEST_FROM_BEGINNER секунду после регистрации RM_ENLISTED_IN_TRANSACTION.

Мы не можем понять, откуда этот запрос прерывания, или почему он был поднят. SQL, вызывающий проблему, - это простой SELECT, который мы можем выполнить без проблем через наш клиент базы данных.

Приложение работает большую часть времени, только изредка отображая эту проблему.

Мы используем Oracle 10.2.0.5.0 с Entity Framework.

UPDATE

Следуя советам @Astrotrain, я установил регистрацию в System.Transactions. Полученная окончательная запись буквально отрезана на полпути, хотя:

....
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Information">
<TraceIdentifier>http://msdn.microsoft.com/2004/06/System/Transactions/TransactionScopeCreated</TraceIdentifier>
<Description>TransactionScope Created</Description>
<AppDomain>BillLineGeneratorUI.exe</AppDomain>
<ExtendedData xmlns="http://schemas.microsoft.com/2004/03/Transactions/TransactionScopeCreatedTraceRecord">
<TraceSource>[Base]

Как вы видите, исключение фактически предотвращает завершение журнала. Что я могу узнать из этого? Любые идеи?

4b9b3361

Ответ 1

Вместо использования средства отслеживания MSDTC (которое я нахожу ужасно спартанским), я могу рекомендовать использовать источник трассировки System.Transactions - просто включите следующее в свой web.config:
Если вы откроете файлы журнала с помощью SvcTraceViewer.exe, вы получите красивое визуальное представление шагов.

<configuration>
  <system.diagnostics>
   <trace autoflush="true" />
   <sources>
     <source name="System.Transactions" switchValue="Information">
       <listeners>
         <add name="tx"
              type="System.Diagnostics.XmlWriterTraceListener"
              initializeData="C:\MyApp-transactions-log.svclog" />
       </listeners>
     </source>
   </sources>
  </system.diagnostics>
</configuration>

Не решение как таковое, но это может дать вам дополнительную информацию о том, что происходит не так.

Ответ 2

Как вы упомянули "Приложение работает большую часть времени, только изредка отображая эту проблему". этим мы можем заключить, что поставщик поддерживает распределенные транзакции, и причиной является некоторый другой прерывистый сбой в соединении или обработке.

  • Используете ли вы области вложенных транзакций, потому что если по какой-то причине внутренняя область откатывается (размещается без вызова завершена), которая немедленно откатывает внешнюю транзакцию, вызывающую ошибку. Используйте TransactionScopeOption.Required(RequiresNew также будет делать, но RequiresNew имеет другие связанные с ним проблемы, связанные с ним, поэтому лучше использовать Required) для решения этой проблемы.

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

Ответ 3

У нас тоже была эта проблема. Лучший способ решить эту проблему, похоже, открывает новое соединение с базой данных и просто выполняет необходимые транзакции. Держать транзакции как можно меньше всегда хорошо.

 DatabaseContext db1 = new DatabaseContext();

 doSomeDatabaseActions(db1);

 TransactionOptions transOpts = new TransactionOptions();
 transOpts.IsolationLevel = System.Transactions.IsolationLevel.Serializable;

 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, transOpts))
 {
     using (DatabaseContext db2 = new DatabaseContext())
     {
        doDatabaseChecksWithLock(db2);
        doChanges(db2);
        db2.SaveChanges();
     }

     scope.Complete();
  }

У нас была проблема без введения второго соединения. Обратите внимание, что ошибка также исчезла с использованием 1 соединения (db1), если транзакция была увеличена (сделана doSomeDatabaseActions часть транзакции).

Ответ 4

Это может быть комментарий, но он слишком большой. Надеюсь, это поможет.

Одна из самых типичных ошибок в вложенных транзакциях такова:

using(TransactionScope outerScope = new TransactionScope())
{
    // Execute query 1

    using(TransactionScope innerScope = new TransactionScope())
    {
        try
        {
            // Execute query 2
        }
        catch (Exception)
        {
        }

        innerScope.Complete();
    }

    outerScope.Complete();
}

Теперь, если запрос 2, который находится внутри блока try/catch, выдает ошибку, вы поймаете исключение в блоке try/catch и обработаете его, но здесь supprise приложение будет вызывать ObjectDisposedException в строке 15, когда вы пытаетесь завершить транзакцию. Это связано с тем, что DTC уже поймал исключение, и, хотя вы его обработали, объекты TransactionScope, которые уже были удалены кодом .Net и транзакцией, были отброшены. Обратите внимание, что я сказал "объекты", это потому, что оба объекта TransactionScope были удалены, поскольку они являются частью одной и той же транзакции.