Найти все операторы sql в xaction, которые заблокированы из дампа памяти

#sql-server #sql-server-2008 #debugging #windbg #memory-dump

#sql-server #sql-server-2008 #отладка #windbg #дамп памяти

Вопрос:

Окружающая среда:
Sql server 2008 r2
Windows 7 64 бит
Windbg 64 бит

Что я уже знаю

  1. Я могу найти sql stmts в этих транзакциях, запустив трассировку профилировщика на стороне сервера и остановив ее, как только возникнет взаимоблокировка. А затем выполнить поиск идентификатора транзакции в файлах трассировки. Но это метод грубой силы, и его не всегда можно выполнить в производственной среде.

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

Проблема:

Я создаю дамп памяти, используя расширенные события в sql server, когда 2 транзакции взаимоблокировки (событие lock_deadlock).

Я вручную создаю этот сценарий взаимоблокировки через management Studio. Допустим, 1 из заблокированных xaction содержит 2 оператора sql.

 begin tran
  update tabl1 ... -- sql stmt 1
go
  update tabl2 ..  -- sql stmt 2
  

Теперь я нахожу этот поток в своем дампе памяти, и я могу найти только мой sql stmt 2, т.е. «обновить таблицу 2».

Могу ли я в любом случае просмотреть все sql stmt, которые поток выполнил в xaction, т.Е. в нашем случае «обновить таблицу 1 ..»?
Я хочу знать, что поток выполнял ранее в той же транзакции. Поскольку это xaction еще не зафиксировано во время дампа, значения должны быть где-то в памяти потока.

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

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ

Справочная информация:
у нас есть среда тестирования производительности, где мы проводим 12-часовые нагрузочные тесты. На следующее утро мы анализируем и обнаруживаем тупик. Приложение выполняет 7-8 операторов dml в транзакции (мы используем hibernate ). Поскольку sys.dm_exec_sql_text based даст результат, только если он находится в кэше, мы не получим весь набор операторов dml, поскольку мы анализируем его на следующий день (ps: я даже не пробовал это, когда мне сообщили о проблеме через 1 день)

Как мы решили эту проблему сегодня:
1. Настройка трассировки на стороне сервера
2. Настройка уведомления о событии, которое срабатывает при взаимоблокировке, и вызов sp, который останавливает трассировку.
3. Из расширенного отчета xml или профилировщика событий мы находим идентификатор транзакции и просматриваем прошлые операторы, соответствующие ему.

Как я думал, я мог бы решить эту проблему:
1. Вызвать дамп памяти при расширенном событии «lock_deadlock» с включенным системным идентификатором.
2. Каким-то образом попытайтесь найти историю в потоке, соответствующем системному идентификатору.

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

Ответ №1:

Вы переусердствовали с этим. Я не утверждаю, что знаю все сложные детали памяти потока, но у него нет причин сохранять последний выполненный оператор локальным, он не нужен для выполнения отката транзакции, что выполняется с использованием записей журнала из журнала транзакций, если это необходимо. Все, что вам нужно для определения причины взаимоблокировки, уже содержится в XML-графе взаимоблокировки. Вам определенно не нужен дамп памяти, чтобы понять это. Стек выполнения TSQL для каждого из процессов содержится в элементе под процессом. Например:

   <process-list>
    <process id="process807b6bc8" taskpriority="0" logused="0" waitresource="KEY: 14:72057594038845440 (1a39e6095155)" waittime="4739" ownerId="163539" transactionname="INSERT EXEC" lasttranstarted="2011-10-05T12:29:22.580" XDES="0x82b318b0" lockMode="S" schedulerid="2" kpid="1764" status="suspended" spid="57" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2011-10-05T12:29:04.563" lastbatchcompleted="2011-10-05T12:29:04.563" clientapp="Microsoft SQL Server Management Studio - Query" hostname="SQL2K8R2-IE2" hostpid="3736" loginname="SQLSKILLSDEMOSadministrator" isolationlevel="read committed (2)" xactid="163539" currentdb="14" lockTimeout="4294967295" clientoption1="673187936" clientoption2="390200">
      <executionStack>
        <frame procname="" line="3" stmtstart="118" stmtend="284" sqlhandle="0x03000e0020c96c7ef2b3cd00739f00000100000000000000" />
        <frame procname="" line="3" stmtstart="50" stmtend="146" sqlhandle="0x02000000e00b66366c680fabe2322acbad592a896dcab9cb" />
      </executionStack>
      <inputbuf>
WHILE (1=1) 
BEGIN
    INSERT INTO #t1 EXEC BookmarkLookupSelect 4
    TRUNCATE TABLE #t1
END
   </inputbuf>
    </process>
    <process id="process807b7288" taskpriority="0" logused="228" waitresource="KEY: 14:72057594038910976 (e5b3d7e750dd)" waittime="4742" ownerId="163545" transactionname="UPDATE" lasttranstarted="2011-10-05T12:29:22.587" XDES="0x82b6f950" lockMode="X" schedulerid="2" kpid="12" status="suspended" spid="58" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2011-10-05T12:29:10.607" lastbatchcompleted="2011-10-05T12:29:10.600" clientapp="Microsoft SQL Server Management Studio - Query" hostname="SQL2K8R2-IE2" hostpid="3736" loginname="SQLSKILLSDEMOSadministrator" isolationlevel="read committed (2)" xactid="163545" currentdb="14" lockTimeout="4294967295" clientoption1="673187936" clientoption2="390200">
      <executionStack>
        <frame procname="" line="4" stmtstart="120" stmtend="262" sqlhandle="0x03000e0059ed607ff3b3cd00739f00000100000000000000" />
        <frame procname="" line="4" stmtstart="82" stmtend="138" sqlhandle="0x020000002a7093322fbd674049d04f1dc0f3257646c4514b" />
      </executionStack>
      <inputbuf>
SET NOCOUNT ON
WHILE (1=1) 
BEGIN
    EXEC BookmarkLookupUpdate 4
END
   </inputbuf>
    </process>
  </process-list>
  

Все, что вам нужно сделать, это взять информацию о sqlhandle и смещении из фреймов, и вы можете получить инструкции в стеке TSQL обратно, используя sys.dm_exec_sql_text() . Вы не сможете этого сделать, если пытаетесь вручную выполнять отдельные операторы по одному, чтобы вызвать взаимоблокировку, поскольку в каждом стеке будет только один оператор, который вы выполнили в нем.

ОБНОВЛЕНИЕ ИЗ ДОПОЛНИТЕЛЬНОЙ ИНФОРМАЦИИ:

Альтернативное использование уведомлений о событиях с внутренней активацией очереди для сбора дополнительной информации — лучший способ сделать то, что вы хотите, и это будет намного дешевле, чем выполнение дампа памяти. Хранимая процедура активации выполняется для уведомления о событии для асинхронного сбора данных, где дамп памяти выполняется синхронно в потоке запуска в расширенных событиях как действие.

Комментарии:

1. Я просмотрел дамп, используя .foreach (obj {s -[1]u 0 l?fffffff «update»}) {.printf » n%mu»,$ {obj}} и я смог найти 2-й sql stmt, но не первый. Спасибо за вашу помощь, Джонатан.