如何查找闲置交易的详情及原因?

Mag*_*ier 4 process sql-server-2008-r2 transaction

我已经开始使用“Idera SQL check”工具。它显示了 Sql Server 系统上每个活动进程的浮动气泡: 流程

这些气泡周围有红色边框,以防交易闲置。传说这很危险:

交易闲置

这些是与 spid 200 相关的一些特定示例信息:

spid           : 200
kpid           : 0
blocked        : 0
waittime       : 0
lastwaittype   : MISCELLANEOUS
waitresource   : 
dbid           : 5
database       : DBNAME
uid            : 1
cpu            : 0
physical_io    : 0
memusage       : 3
login_time     : 29.02.2016 09:37:17
last_batch     : 29.02.2016 09:37:17
ecid           : 0
open_tran      : 1
status         : SERVERNAME
program_name   : PROGRAMNAME
host_process   : 5380
cmd            : AWAITING COMMAND
nt_damain      : 
nt_username    : 
net_address    : 99887766
net_library    : TCP/IP
loginname      : sqlusername
stmt_start     : 0
stmt_end       : 0
input_buffer   : 
Run Code Online (Sandbox Code Playgroud)

很明显这是危险的。但我很难找出原因。查看sys.sysprocessesDMV 以找出在这些 spid 上下文中执行的查询。执行的查询运行速度非常快,不适合长时间运行。所以我不明白为什么他们在交易中变得闲置?如何找出背景?

编辑:获取进程的幕后查询如下:

exec sp_executesql N'
            SELECT p.spid, p.kpid, p.blocked, CAST(p.waittime AS BIGINT) as waittime, p.lastwaittype, p.waitresource, p.dbid, db.name as [database], p.uid, CAST(p.cpu / 1000 AS BIGINT) as cpu, 
            CAST(p.physical_io AS BIGINT) as physical_io, p.memusage,
            p.login_time, p.last_batch , p.ecid , CAST(p.open_tran AS BIGINT) as open_tran, p.status, p.hostname, p.program_name, p.hostprocess, p.cmd, p.nt_domain, p.nt_username, p.net_address,
            p.net_library, p.loginame, p.stmt_start, p.stmt_end
            FROM master.dbo.sysprocesses p join master.dbo.sysdatabases db on p.[dbid] = db.[dbid]
            Where hostprocess <> '''' AND program_name <> @application',N'@application nvarchar(17)',@application=N'Idera.Application'
Run Code Online (Sandbox Code Playgroud)

看起来 OPEN_TRANS 表示事务中的进程并具有红色边框。红色边框的厚度随着时间的推移而增加,这意味着该过程在结果集中的时间越长,红色边框就越厚。

spa*_*dba 5

这是我用来识别持有锁的空闲事务的查询。

SELECT 
    CAST(SERVERPROPERTY('ServerName') AS sysname) AS ServerName
    ,s.session_id
    ,s.status
    ,s.login_time
    ,s.host_name
    ,s.program_name
    ,s.host_process_id
    ,s.original_login_name
    ,s.last_request_end_time
    ,CAST(t.text AS nvarchar(4000)) AS [text]
    ,CAST(s.context_info AS varchar(128)) AS [context_info]
FROM sys.dm_exec_sessions AS s
INNER JOIN sys.dm_exec_connections AS c
    ON s.session_id = c.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 s.session_id = st.session_id 
) AS trans
CROSS APPLY sys.dm_exec_sql_text(most_recent_sql_handle) AS t
WHERE s.session_id NOT IN (
        SELECT session_id
        FROM sys.dm_exec_requests
    )
    AND s.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 program_name NOT LIKE '%SQLAgent - Job Manager%'
OPTION (RECOMPILE, FORCE ORDER);
Run Code Online (Sandbox Code Playgroud)

它们危险的原因很简单:它们持有锁但什么也不做,等待应用程序提交或回滚事务。

当应用程序在客户端执行一些繁重的任务,而不与数据库交互,但仍保持事务打开时,通常会发生这种情况。最糟糕的情况是应用程序在事务期间显示错误消息或等待用户输入。

如果您想知道发生了什么,您需要追踪这些应用程序并了解它们在保持事务打开的同时正在做什么。