私は最近、トランザクションが開いている開発サーバー(SQL Server 2016)にいくつかの接続がハングしていることを発見しました。これらのトランザクションは数日間開いています。次のようにクエリを使用しています。
SELECT session_id, se.database_id, status, open_transaction_count
FROM sys.dm_exec_sessions
WHERE open_transaction_count > 0
AND status = 'sleeping'
AND is_user_process = 1
open_transaction_count = 1のセッションがいくつか返されます。 sys.dm_tran_session_transactionsおよびsys.dm_tran_active_transactionsで返されたsession_idsを確認すると、これらのビューでこれらのトランザクションの存在が証明されます。すべてのトランザクションにはtransaction_state = 2があります。
これらのセッション内の最後のSQLステートメントまたはバッチを確認して、アプリケーションのどのコードがそれを引き起こしているのか、それが問題であることを特定したいと思います。私が使うとき:
DBCC INPUTBUFFER([mySPID])
session_id sの一部に対するクエリを受け取りますが、他の結果はありません。次のようにクエリを実行すると、同じ結果になります。
SELECT se.session_id, se.database_id, se.status, se.open_transaction_count, qry.text
FROM sys.dm_exec_sessions AS se
LEFT JOIN sys.dm_exec_connections AS con ON con.session_id = se.session_id
OUTER APPLY sys.dm_exec_sql_text(con.most_recent_sql_handle) AS qry
WHERE open_transaction_count > 0
AND status = 'sleeping'
AND is_user_process = 1
興味深いのは、「問題のあるデータベース」(クエリテキストが返されないデータベース)に切り替えてDBCC OPENTRANを実行すると、「アクティブなオープントランザクションがない」という結果になることです。私はそれが明示的な閉じられていないトランザクション内のselectステートメントである可能性があると想定しているため、そのようなトランザクションはDBCC OPENTRANで返されません。しかし、私はこの解釈に確信が持てません。
私が知りたいのは、なぜこれらのセッションの最後のステートメント/バッチを取得できないのか、そしてどのようにしてそれを取得できる別の方法(前述)があるのかです。
これは、アプリケーションが 暗黙のトランザクション を使用しているときに発生することがあります
sp_who2 が本当に混乱していることは役に立ちません-実行中のクエリを見つけるには sp_WhoIsActive または sp_BlitzWho を使用するほうがよいでしょう。
暗黙的なトランザクションの1つの死んだプレゼントは、begin tran
やIF @@TRANCOUNT > 0
のようなクエリテキストを参照することです。