0

環境:
SQL Server 2008 r2
Windows764ビット
Windbg64ビット

私がすでに知っていること

  1. サーバー側のプロファイラートレースを実行し、デッドロックが発生するとすぐに停止することで、このトランザクションでsqlstmtsを見つけることができます。次に、トレースファイルでトランザクションIDを検索します。ただし、これはブルートフォース方式であり、実稼働環境で常に実行できるとは限りません。

  2. マイクロソフトにメモリダンプを送信して、それを分析する必要があることはわかっています。しかし、私的なシンボルなしでこれを解決する希望があれば、私は私たちを見つけたいと思います。

問題:

2つのトランザクションがデッドロックしたときにSQLサーバーで拡張イベントを使用してメモリダンプを作成します(lock_deadlockイベント)。

このデッドロックシナリオは、ManagementStudioを介して手動で作成しています。デッドロックされたxactionの1つに2つのSQLステートメントがあるとします。

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

今、私は私のメモリダンプでこのスレッドを見つけました、そして私は私のsql stmt 2、すなわち「updatetabl2」だけを見つけることができます。

とにかく、スレッドがxactionで実行したすべてのSQL stmtを検索できますか?つまり、この場合は「updatetabl1 ..」ですか?
同じトランザクションでスレッドが以前に何を実行したかを知りたい。このxactionはダンプの時点ではまだコミットされていないため、値はスレッドメモリのどこかにあるはずです。

ここで意味がわからない場合はお知らせください。私はしばらくこの問題を抱えていましたが、これが可能かどうか知りたいです。

追加情報

背景:
パフォーマンステスト環境があり、12時間の負荷テストを実行します。翌朝、デッドロックを分析して見つけます。アプリケーションはトランザクションで7〜8個のdmlステートメントを実行します(hibernateを使用します)。sys.dm_exec_sql_textベースは、キャッシュ内にある場合にのみ結果を生成するため、翌日分析しているため、dmlステートメントのセット全体を取得しません(ps:問題が1後に報告されたとき、これを試していませんでした) day)

今日この問題をどのように解決しましたか:
1。サーバー側のトレースを設定します
2.デッドロック時にトリガーされるイベント通知を設定し、トレースを停止するspを呼び出します。
3.拡張イベントxmlレポートまたはプロファイラーから、トランザクションIDを見つけ、それに対応する過去のステートメントを検索します。


この問題を解決できると思った方法:
1.システムIDが含まれている拡張イベント「lock_deadlock」でメモリダンプをトリガーします。
2.どういうわけか、システムIDに対応するスレッドで履歴を見つけようとします。


なぜメモリダンプするのか:
本番環境で実行する必要がある場合、この設定による影響が最も少ないためです。

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とoffsetの情報を取得するだけで、sys.dm_exec_sql_text()を使用してTSQLスタックのステートメントを元に戻すことができます。各スタックには実行した単一のステートメントしか含まれないため、デッドロックをトリガーするために一度に1つのステートメントを手動で実行しようとすると、これを実行できなくなります。

追加情報からの更新:

追加情報を収集するための内部キューのアクティブ化を伴うイベント通知の代替使用は、実行したいことを実行するための最良の方法であり、メモリダンプを実行するよりもはるかに安価です。アクティベーションストアドプロシージャは、イベント通知に対して実行され、データを非同期的に収集します。メモリダンプは、アクションとして拡張イベントの起動スレッドで同期的に実行されます。

于 2011-10-05T16:40:44.217 に答える