web-dev-qa-db-ja.com

SELECTクエリがオープントランザクションを保持するスリープ状態になっているのはなぜですか

Sp_WhoIsActiveを使用すると、多くのプロセスが "スリープ"状態になり、数時間かかる場合があります。原因はわかりませんが、トラブルシューティングを続けています(タイムアウト?コミットされていないトランザクションの不良コード?)。

以下のクエリを使用すると、これらの開いているトランザクションはすべて、「スリープ」状態のSELECTクエリであることがわかりました。 SELECTがトランザクションを開くのはなぜですか?これらがストアドプロシージャのどこかにあり、[TEXT]フィールドに、実行されたプロシージャの最後のステートメントしか表示されていませんか?開いているトランザクションにはwait_infoがありません。

 SELECT [TEXT] as SQLcode 
 FROM SYS.SYSPROCESSES SP
 CROSS APPLY SYS.DM_EXEC_SQL_TEXT(SP.[SQL_HANDLE])AS DEST WHERE OPEN_TRAN=1
1
SomeGuy

睡眠は必ずしも問題ではありません。アプリによっては、何も実行されていなくても、スレッドプーリングによって接続が開いたままになる場合があります。

開いているトランザクションがない場合、それは本当に問題ですか?

ケンドラ・リトルがこれについて最近書いた 彼女のブログ

枕木は通常大丈夫です

開いているトランザクションのないスリープセッション…

テーブルにロックをかけていません

リソースをほとんど使用しません

アプリケーションで再利用できます(接続プーリングなど)

ケンダの提案に従って、sp_who2を使用する代わりに sp_whoisactive を確認してください。

1
Greg

以下のクエリを使い始めて、目的に合わせて調整してください。

select *
from sys.dm_tran_database_transactions t

join sys.dm_tran_session_transactions st on t.transaction_id = st.transaction_id 

join sys.dm_exec_sessions s on s.session_id = st.session_id 

join sys.dm_exec_connections c on c.session_id = s.session_id 

cross apply sys.dm_exec_sql_text(most_recent_sql_handle) 
where 1=1

and text <> 'begin tran' 

and text not like '%sp_MS%' 

and datediff(minute, last_request_end_time, getdate()) > 60

and database_transaction_begin_time is not null

私はこれを以下で使用します、それはほとんどの場合に役立ちます:

    SELECT 
     es.session_id AS session_id

    ,CASE WHEN eS.LOGIN_NAME = eS.ORIGINAL_LOGIN_NAME 
     THEN eS.LOGIN_NAME 
     ELSE eS.LOGIN_NAME + ' (' + eS.ORIGINAL_LOGIN_NAME + ')' 
     END AS LOGIN_NAME

    ,es.Host_name AS hostname
    ,es.status
    ,es.last_request_start_time
    ,es.last_request_end_time
    ,es.CPU_TIME AS CPU_TIME_MS
    ,es.MEMORY_USAGE AS MEMORY_USAGE_PAGES
    ,es.ROW_COUNT
    ,NULL AS blocked_by
    ,NULL AS waittype
    ,NULL AS waittime
    ,NULL AS lastwaittype
    ,NULL AS waitresource
    ,dbid=trans.database_name
    ,NULL as  cmd
    ,t.text AS [QUERY]
    ,NULL AS PARENT_QUERY

   ,TRANSACTION_ISOLATION_LEVEL = NULL

    ,NULL as cpu

    ,NULL AS physical_io

    --,es.open_transaction_count as [open_tran]
    ,es.program_name

    --,es.login_time
    --,ota.task_state
    --,ota.pending_io_count
    --,ota.pending_io_byte_count


    FROM sys.dm_exec_sessions AS es
    INNER JOIN sys.dm_exec_connections AS c
        ON es.session_id = c.session_id

    --LEFT OUTER JOIN sys.dm_os_tasks ota ON es.session_id = ota.session_id

    CROSS APPLY (

        SELECT MAX(DB_NAME(dt.database_id)) AS database_name
        FROM sys.dm_tran_session_transactions AS st
        INNER JOIN sys.dm_tran_database_transactions AS dt
            ON st.transaction_id = dt.transaction_id
        WHERE is_user_transaction = 1
        GROUP BY st.session_id
        HAVING es.session_id = st.session_id 

    ) AS trans

    CROSS APPLY sys.dm_exec_sql_text(c.most_recent_sql_handle) AS t
    WHERE es.session_id NOT IN (

            SELECT session_id
            FROM sys.dm_exec_requests

        )
        AND es.session_id IN (

            SELECT request_session_id
            FROM sys.dm_tran_locks
            WHERE request_status = 'GRANT'
        )
        AND STATUS = 'sleeping'
        AND is_user_process = 1
        AND es.session_id <> @@spid

SYS.SYSPROCESSESの使用は避けてください

1