Как определить, почему время распределенной транзакции истекло - PullRequest
8 голосов
/ 11 ноября 2009

Я использую LINQ to SQL и сторонний SDK, который поддерживает распределенные транзакции. Когда я понимаю, что ожидающее обновление будет обновлять как записи SQL, так и записи в стороннем SDK, я создаю TransactionScope с тайм-аутом 0 (предположительно бесконечный) (хотя я также пробовал 12 часов в качестве параметра timepan). Затем я использую GetDtcTransaction для транзакции окружения (созданной транзакцией), чтобы получить транзакцию DTC для связи со сторонним SDK. Все работает хорошо в течение примерно 10 минут, но через 10 минут транзакция исчезает и возникает ошибка. Как определить, почему транзакция исчезает. Я подозреваю, что это тайм-аут, потому что он регулярно происходит через 10 минут, хотя в этот момент была проделана небольшая работа. Но я не знаю, как определить, чем прервана транзакция, почему и как продлить срок ее службы.

Я пытался отследить следующие события с помощью профилировщика SQL:

  1. Все ошибки и предупреждения
  2. Все события безопасности, кроме событий «Объект схемы аудита»
  3. Все события Transaction, кроме событий SQLTransaction и TransactionLog

Все, что я узнаю во время ошибки, это следующие события:

<Event id="19" name="DTCTransaction">
  <Column id="3" name="DatabaseID">1</Column>
  <Column id="11" name="LoginName">sa</Column>
  <Column id="35" name="DatabaseName">master</Column>
  <Column id="51" name="EventSequence">167065</Column>
  <Column id="12" name="SPID">10</Column>
  <Column id="60" name="IsSystem">1</Column>
  <Column id="1" name="TextData">{D662BBC4-21EC-436D-991C-DCB061A34782}</Column>
  <Column id="21" name="EventSubClass">16</Column>
  <Column id="25" name="IntegerData">0</Column>
  <Column id="41" name="LoginSid">01</Column>
  <Column id="49" name="RequestID">0</Column>
  <Column id="2" name="BinaryData">C4BB62D6EC216D43991CDCB061A34782</Column>
  <Column id="14" name="StartTime">2009-11-11T13:55:32.82-06:00</Column>
  <Column id="26" name="ServerName">.</Column>
  <Column id="50" name="XactSequence">0</Column>
</Event>
<Event id="33" name="Exception">
  <Column id="3" name="DatabaseID">9</Column>
  <Column id="11" name="LoginName">sa</Column>
  <Column id="31" name="Error">1222</Column>
  <Column id="35" name="DatabaseName">ACS</Column>
  <Column id="51" name="EventSequence">167066</Column>
  <Column id="12" name="SPID">19</Column>
  <Column id="20" name="Severity">16</Column>
  <Column id="60" name="IsSystem">1</Column>
  <Column id="1" name="TextData">Error: 1222, Severity: 16, State: 18</Column>
  <Column id="41" name="LoginSid">01</Column>
  <Column id="49" name="RequestID">0</Column>
  <Column id="14" name="StartTime">2009-11-11T13:55:34.717-06:00</Column>
  <Column id="26" name="ServerName">.</Column>
  <Column id="30" name="State">18</Column>
  <Column id="50" name="XactSequence">0</Column>
</Event>
<Event id="33" name="Exception">
  <Column id="31" name="Error">8525</Column>
  <Column id="8" name="HostName">MARTY755</Column>
  <Column id="12" name="SPID">55</Column>
  <Column id="20" name="Severity">16</Column>
  <Column id="64" name="SessionLoginName">fse</Column>
  <Column id="1" name="TextData">Error: 8525, Severity: 16, State: 1</Column>
  <Column id="9" name="ClientProcessID">2516</Column>
  <Column id="41" name="LoginSid">DB2744F54B5CDB4A8B9E5CA9C209A7AC</Column>
  <Column id="49" name="RequestID">0</Column>
  <Column id="10" name="ApplicationName">.Net SqlClient Data Provider</Column>
  <Column id="14" name="StartTime">2009-11-11T13:55:37.54-06:00</Column>
  <Column id="26" name="ServerName">.</Column>
  <Column id="30" name="State">1</Column>
  <Column id="50" name="XactSequence">236223201284</Column>
  <Column id="3" name="DatabaseID">9</Column>
  <Column id="11" name="LoginName">fse</Column>
  <Column id="35" name="DatabaseName">ACS</Column>
  <Column id="51" name="EventSequence">167067</Column>
</Event>
<Event id="162" name="User Error Message">
  <Column id="31" name="Error">8525</Column>
  <Column id="8" name="HostName">MARTY755</Column>
  <Column id="12" name="SPID">55</Column>
  <Column id="20" name="Severity">16</Column>
  <Column id="64" name="SessionLoginName">fse</Column>
  <Column id="1" name="TextData">Distributed transaction completed. Either enlist this session in a new transaction or the NULL transaction.</Column>
  <Column id="9" name="ClientProcessID">2516</Column>
  <Column id="41" name="LoginSid">DB2744F54B5CDB4A8B9E5CA9C209A7AC</Column>
  <Column id="49" name="RequestID">0</Column>
  <Column id="10" name="ApplicationName">.Net SqlClient Data Provider</Column>
  <Column id="14" name="StartTime">2009-11-11T13:55:37.54-06:00</Column>
  <Column id="26" name="ServerName">.</Column>
  <Column id="30" name="State">1</Column>
  <Column id="50" name="XactSequence">236223201284</Column>
  <Column id="3" name="DatabaseID">9</Column>
  <Column id="11" name="LoginName">fse</Column>
  <Column id="35" name="DatabaseName">ACS</Column>
  <Column id="51" name="EventSequence">167068</Column>
</Event>

EventSubClass 16 в событии DTCTransaction указывает «транзакция прерывается».

Ответы [ 3 ]

8 голосов
/ 20 ноября 2009

Чтобы увеличить время ожидания, которое по умолчанию составляет максимум 10 минут, если оно не указано, необходимо обновить C: \ WINDOWS \ Microsoft.NET \ Framework \ v2.0.50727 \ CONFIG \ Machine.config в целевой системе (см. C : \ Windows \ Microsoft.NET \ Framework64 \ v2.0.50727 \ CONFIG, если вы используете 64-разрядную версию). Добавьте это как последний элемент прямо под корневым уровнем:

<system.transactions>
    <machineSettings maxTimeout="23:00:00"/>
</system.transactions>

Это (в качестве примера) установит время ожидания на 23 часа.

Действующее значение отображается в System.Transactions.TransactionManager.MaximumTimeout

2 голосов
/ 29 января 2010

Это, наверное, очевидно для всех, кто читает, кроме меня, но я просто застрял в этой проблеме и хотел упомянуть, как я ее исправил. Несмотря на то, что я изменил файл в месте, указанном BlueMonkMN, я все еще получал тайм-аут транзакции по умолчанию, равный 10 минутам. Поскольку я использую 64-разрядную версию Windows 7, расположение файла machine.config для .NET находится по следующему адресу:

C:\Windows\Microsoft.NET\Framework64\v2.0.50727\CONFIG

Обратите внимание, что папка "Framework64" отличается от указанной выше.

2 голосов
/ 11 ноября 2009

Может ли это быть время ожидания SqlConnection, а не распределенная транзакция?

Обновление 1

Вы можете использовать SQL Server Profiler , чтобы попытаться отследить неожиданное падение соединения. Вы просто должны убедиться, что ваш профиль трассировки содержит только те события, которые необходимо отслеживать, поскольку его вывод может быть довольно многословным. Я бы начал с мониторинга только событий «Аудит входа» и «Выход из системы», которые можно найти в категории событий «Аудит безопасности».

Если вы профилируете что-либо, кроме автономного / используемого только для себя экземпляра SQL Server, вы, вероятно, захотите применить фильтр, чтобы в выходных данных отображались только события, исходящие от вашего хоста.

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

Обновление 2

Из вашего журнала трассировки я вижу два исключения, детали которых:

  • Ошибка: 1222, уровень серьезности: 16, состояние: 18
  • Ошибка: 8525, серьезность: 16, состояние: 1

Гуглил для исключения 1222 обнаружился http://www.sqlservercentral.com/Forums/Topic579864-146-1.aspx#bm645422,, который гласит:

Эта ошибка означает, что блокировка была запрошено в msdb и истекло время ожидания. Обычно это будет означать, что это большая транзакция на большой временной таблице или большой сорт или что-то в этом роде.

Есть ли у вас какие-то особенные долгосрочные запросы, которые могут быть связано с этим? Возможно тяжелый дежурный отчет, или что-то похожее на что?

Надеюсь, это немного продвинет вас.

...