0

Environment:
Sql server 2008 r2
Windows 7 64 bit
Windbg 64bit

What i already know

  1. I can find the sql stmts in this transactions by running a server-side profiler trace and stopping it as soon as there is a deadlock. And then searching for the transaction Id in the trace files. But this is a brute force method and cannot always be done on a production environment.

  2. I know i should send memory dump to microsoft and get then analyze it. But i want to find our if there is any hope to solve this without private symbols.

Problem:

I create a memory dump using extended events in sql server when 2 transactions deadlock ( lock_deadlock event).

I am manually creating this deadlock scenario via management studio. Lets say 1 of the deadlocked xaction has 2 sql statements in it.

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

Now i find this thread in my memory dump and i am able to find out only my sql stmt 2 i.e "update tabl2".

Is there anyway i can look up all the sql stmts that thread had executed in the xaction i.e. in our case "update tabl1.." ?
I want to know what the thread had executed before in the same transaction. Since this xaction is not committed yet at the time of the dump, the values should be somewhere in the thread memory.

Please let me know if i dont make sense here. I have been after this problem for a while and i want to know if this possible or not.

ADDITIONAL INFO

Background:
We have performance testing env, where we run 12 hour load tests. Next morning we analyze and find out a deadlock. Application executes 7-8 dml statements in a transaction ( we use hibernate ). Since sys.dm_exec_sql_text based will yield result only if its in the cache, we dont get the whole set of dml statements as we are analyzing it the next day (ps: i didnt even try this, when the problem was reported to me after 1 day)

How did we solve this problem today:
1. Setup server side trace
2. Setup event notification which triggers on deadlock and call a sp which stops the trace.
3. From extended event xml report or profiler, we find transaction id and look up the past statements corresponding to same.


How i thought i could solve this problem:
1. Trigger memory dump on extended event "lock_deadlock" with system id included.
2. Somehow try to find history in the thread corresponding to the system id.


Why memory dump:
Because this setup will cause least impact if i have to do it on production.

4

1 回答 1

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="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 和偏移量信息,然后您可以使用 sys.dm_exec_sql_text() 将 TSQL 堆栈中的语句取回。如果您尝试一次手动执行一个语句来触发死锁,您将无法执行此操作,因为每个堆栈只会包含您在其中执行的单个语句。

从附加信息更新:

使用带有内部队列激活的事件通知来收集附加信息的替代方法是执行您想要完成的操作的最佳方式,它比执行内存转储要便宜得多。为事件通知执行激活存储过程以异步收集数据,其中内存转储在扩展事件中作为操作在触发线程上同步执行。

于 2011-10-05T16:40:44.217 回答