Найти все операторы SQL в xaction, которые заблокированы из дампа памяти - PullRequest
0 голосов
/ 05 октября 2011

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

Что я уже знаю

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

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

Проблема:

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

Я вручную создаю этот сценарий тупика через студию управления. Допустим, 1 из зашедшего в тупик xaction содержит 2 оператора sql.

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

Теперь я нахожу эту ветку в своем дампе памяти и могу найти только мой sql stmt 2, т. Е. "Update tabl2".

В любом случае я могу посмотреть все sql stmts, которые поток выполнил в xaction, т.е. в нашем случае "update tabl1 .."?
Я хочу знать, что поток выполнял ранее в той же транзакции. Поскольку это действие еще не зафиксировано во время создания дампа, значения должны находиться где-то в памяти потока.

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

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

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

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


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


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

1 Ответ

1 голос
/ 05 октября 2011

Вы закончили это.Я не утверждаю, что знаю все сложные детали памяти потока, но нет никаких оснований для того, чтобы сохранять последний выполненный оператор локальным, ему не требуется выполнять откат транзакции, что делается с использованием журналазаписи из журнала транзакций, если это необходимо.Все, что вам нужно, чтобы выяснить причину тупика, уже содержится в графе взаимоблокировки 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="SQLSKILLSDEMOS\administrator" 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="SQLSKILLSDEMOS\administrator" 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 ().Вы не сможете сделать это, если вы попытаетесь вручную выполнить отдельные операторы по одному, чтобы вызвать взаимоблокировку, поскольку в каждом стеке будет только один оператор, который вы выполнили.

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

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

...