使用 sp_WhoIsActive 监视活动

sp_WhoIsActive存储过程可以监视SQL Server中当前正在运行的活动。

介绍

如果服务器速度变慢时,数据库管理员需要不断检查SQL Server实例上正在运行的操作。

系统存储过程“sp_who”和“sp_who2”可以检查实例上所有正在运行的进程,但它们缺乏很多有助于性能监控和分析过程的有用信息,也显示了很多如系统进程等无用的信息。

为此,Adam Machanic(自 2004 年起成为 Microsoft MVP)开发了一个名为“sp_whoisactive”的更强大的存储过程,以填补 DBA 的实际需求与当前提供的过程(sp_who 和 sp_who2)之间的差距。

下面将会简要介绍sp_who和sp_who2存储过程,及如何使用sp_whoisactive

sp_Who和sp_Who2介绍

官方介绍,sp_who提供有关 Microsoft SQL Server 数据库引擎实例中当前用户、会话和进程的信息。可以过滤信息以仅返回那些非空闲、属于特定用户或属于特定会话的进程。

sp_who返回诸如会话进程ID (SPID-session process ID)、执行上下文ID (ECID-execution context ID)、进程状态(status)、阻塞会话ID(blk)、数据库名称(dbname)、与此进程关联的登录名(loginame)和主机名(hostname)以及命令类型(Cmd-command type)等信息。

blk为阻塞执行的会话ID

sp_Who2与sp_Who类似,但没有文档记录也没有支持,但它从当前进程返回更多信息和性能计数器,例如执行命令的程序名称(ProgramName)、磁盘IO(DiskIO-磁盘读写总次数)、CPU时间(CPUTime-占用CPU运行的总时间)、上次批处理执行时间(LastBatch-最后一次调用存储过程或者执行查询的时间)。

如截图所示,输出显示了包含不需要的所有正在运行的系统和用户进程,并且只能使用loginname和sessionid过滤结果。而实际可能需要隐藏系统进程。

并且,以上输出不包含任何有关当前运行的SQL命令的信息,如开始执行时间、执行持续时间、等待信息等。

sp_Who和sp_Who2返回活动的、某个用户或SPID的进程信息

  • 返回某个用户的进程信息

如下,返回sa用户的会话进程信息

exec sp_who 'sa';-- exec sp_who2 'sa';
-- exec sp_who @loginame='sa';

  • 返回活动的进程信息
exec sp_who 'ACTIVE';-- EXEC sp_who2 'active';

  • 返回指定进程ID的信息
exec sp_who2 '1';
exec sp_who2 1;-- exec sp_who '1';
-- exec sp_who 1;

保存sp_Who2过滤结果

如下,有个示例可以保存sp_Who2的结果到表或表变量或临时表中。用于过滤显示

DECLARE @Table TABLE(SPID INT,Status VARCHAR(MAX),LOGIN VARCHAR(MAX),HostName VARCHAR(MAX),BlkBy VARCHAR(MAX),DBName VARCHAR(MAX),Command VARCHAR(MAX),CPUTime INT,DiskIO INT,LastBatch VARCHAR(MAX),ProgramName VARCHAR(MAX),SPID_1 INT,REQUESTID INT
)INSERT INTO @Table EXEC sp_who2SELECT  *
FROM    @Table
WHERE ....

借助sysprocesses获取类似信息:

SELECT  spid,sp.[status],loginame [Login],hostname, blocked BlkBy,sd.name DBName, cmd Command,cpu CPUTime,physical_io DiskIO,last_batch LastBatch,[program_name] ProgramName
FROM master.dbo.sysprocesses sp
JOIN master.dbo.sysdatabases sd ON sp.dbid = sd.dbid
ORDER BY spid

下载安装whoisactive存储过程

可以直接从whoisactive下载页下载该存储过程,或者GitHub repository。

最新版是2018发布的,适用于SQL Server2005+所有的版本。

下载后解压缩,并打开who_is_active.sql文件,在SSMS中执行(who_is_active_v11_32.sql)

使用sp_Whoisactive

exec sp_Whoisactive;

执行后,可以看到,默认仅返回正在运行的用户进程,并提供每个进程下面的信息:

sp_Whoisactive信息和sp_who、sp_who2对比:


sp_Whoisactive输出列信息的介绍

上面的对比已经对列进行了简要的介绍,下面再多做些说明。

  • dd hh:mm:ss:mss:显示命令的持续时间(执行时间)。可以使用此列来识别长时间运行的事务。例如,可以识别运行时间超过 1 小时的 SQL Server 会话。 它显示一个活动请求的查询运行时间。 在睡眠会话(sleeping session)的情况下,它显示自上次完成批以来的时间
  • session_id:用户会话的 SP ID。
  • Sql_text:正在运行的会话的SQL文本。它是一个超链接,点击它并获得完整的t-SQL。
  • Login name:是连接到SQL Server并执行会话中指定的SQL的登录名
  • Wait_info:它是一个有用的列,用于识别 SPID 的当前等待,例如 CXPACKET、ASYNC_NETWORK_IO 以及等待时间。请参阅有关 SQL Server等待类型的文章。
  • Tempdb_allocationstempdb_current:如果查询正在使用 TempDB 数据库,可以使用此列获取有关 tempdb 分配的信息。例如,如果我们使用一个表变量或临时表,它会在 TempDB 中创建,我们可以使用这两个列来跟踪信息。
  • CPU:从中得到查询消耗的总 CPU 时间。
  • Blocking_session_id:在阻塞的情况下,可以从这个列中获取阻塞的session-id。
  • Readswrites:给出当前查询的读写次数。
  • Open_tran_count:当前会话打开的事务数。
  • Percent complete:通常可以使用DMV sys.dm_exec_requests 检查少数命令完成状态的百分比,例如备份和恢复数据库命令。Sp_WhoIsActive使用该DMV信息并将其显示输出。
  • Program name:给出了用户连接的应用程序名称,例如 Microsoft SQL Server Management Studio – Query、Azure Data Studio、SQL Server Agent 等。

更多的详细参数介绍推荐查看SQL Server - Using SP WhoIsActive to identify Locks, Blocks, Slow Queries, Running Queries, and more中的介绍

sp_whoisactive显示系统进程

Exec sp_whoisactive @show_system_spids = 1;

还可以使用@get_additional_info、@get_locks、@get_avg_time等参数查看更多信息。

sp_Whoisactive的@help参数

sp_whoisactive比较吸引人的一个功能是@help参数。所有相关信息都可以通过执行以下命令获得:

Exec sp_whoisactive @help = 1;

help命令包含三个部分:

  1. 一般信息:提供版本、版权、网站、反馈邮箱、URL等一般信息
  2. 参数说明:其中提供了所有可用参数及其说明和默认信息的列表
  3. 输出列描述:所有可用输出列的完整列表及其描述

sp_WhoIsActive过程的几个可选参数和用法

@find_block_leaders查看导致阻塞和被阻塞的会话

可以将 @find_block_leaders 参数的值设置为 1 并对 blocks_session_count 列的结果进行排序,用以检查导致阻塞和被阻塞的会话-sessions。

EXEC sp_WhoIsActive@find_block_leaders = 1,@sort_order = '[blocked_session_count] DESC';

从输出结果可以看到,session_id为55的会话导致了阻塞,后面是它阻塞的2个会话

@get_plans获取正在查询的执行计划

假设我们正在调查 SQL Server 中的性能问题,并且发现了有问题的查询。如果能得到对应的执行计划来查看查询执行中涉及的成本高的操作,那就太好了。

此时,可以指定参数@get_plans=1,它会在输出中附加一个带 XML 执行计划的列。

EXEC sp_WhoIsActive @get_plans = 1;

query_plan列输出执行计划,必须为当前正在执行的查询语句。如果已经执行完,或没有正在执行的SQL语句,将会返回NULL

点击查询计划(query_plan),可以看到该查询的执行计划。

@get_locks获取详细的锁信息

可以使用这个参数来获取一个 XML 片段,里面是有关 SQL Server 会话中持有的锁的详细信息。在输出中,会多出一个额外的locks列。如下所示,单击locks,将看到 XML 格式的详细锁信息。

EXEC sp_WhoIsActive @get_locks = 1;

@get_additional_info获取额外的会话参数信息

我们可以设置几个可能影响查询性能的会话参数。 Sp_WhoIsActive提供的参数 @get_additional_info ,会显示有关这些参数的信息。同样会额外输出一列,列为additional_info。

EXEC sp_WhoIsActive @get_additional_info = 1;

保存sp_whoisactive历史数据

获取sp_whoisactive结果表的创建脚本

sp_WhoIsActive提供了它的结果表的创建脚本,直接使用输出参数@schema即可获得。

declare @HistTableName VARCHAR(MAX)= 'HistWhoIsActive';
declare @schema VARCHAR(MAX);
EXEC sp_WhoIsActive @get_transaction_info = 1,@get_outer_command = 1,@get_plans = 1,@return_schema = 1,@schema = @schema OUTPUT;-- 输出<table_name>占位组成的创建表的脚本
select @schema;-- 生成创建表的脚本并执行创建
EXEC (REPLACE(@schema, '<table_name>', @destination_table));

在代理作业中计划执行sp_whoisactive

如果想要定期保存正在运行的进程信息以供进一步分析,则可以将sp_whoisactive放在代理作业中执行保存到表中。

创建一个新job并将以下代码放入作业步骤(job step·),根据需要修改前3个变量。如果不存在,代码将创建日志记录表,如果不存在则创建聚集索引,记录当前的活动并根据@retention变量清除旧数据。

应该多久收集一次活动?原作者认为每30-60秒收集一次 sp_WhoIsActive 数据,这是一个在记录足够的活动以解决生产问题和非常繁忙的环境中保持所需的数据存储之间的良好平衡。

如下,也可以将其改为一个存储过程来处理:

SET NOCOUNT ON;DECLARE @retention INT = 7,@destination_table VARCHAR(500) = 'WhoIsActive',@destination_database sysname = 'Crap',@schema VARCHAR(MAX),@SQL NVARCHAR(4000),@parameters NVARCHAR(500),@exists BIT;SET @destination_table = @destination_database + '.dbo.' + @destination_table;--create the logging table
IF OBJECT_ID(@destination_table) IS NULLBEGIN;EXEC dbo.sp_WhoIsActive @get_transaction_info = 1,@get_outer_command = 1,@get_plans = 1,@return_schema = 1,@schema = @schema OUTPUT;SET @schema = REPLACE(@schema, '<table_name>', @destination_table);EXEC ( @schema );END;--create index on collection_time
SET @SQL= 'USE ' + QUOTENAME(@destination_database)+ '; IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(@destination_table) AND name = N''cx_collection_time'') SET @exists = 0';
SET @parameters = N'@destination_table varchar(500), @exists bit OUTPUT';
EXEC sys.sp_executesql @SQL, @parameters, @destination_table = @destination_table, @exists = @exists OUTPUT;IF @exists = 0BEGIN;SET @SQL = 'CREATE CLUSTERED INDEX cx_collection_time ON ' + @destination_table + '(collection_time ASC)';EXEC ( @SQL );END;--collect activity into logging table
EXEC dbo.sp_WhoIsActive @get_transaction_info = 1,@get_outer_command = 1,@get_plans = 1,@destination_table = @destination_table;--purge older data
SET @SQL= 'DELETE FROM ' + @destination_table + ' WHERE collection_time < DATEADD(day, -' + CAST(@retention AS VARCHAR(10))+ ', GETDATE());';
EXEC ( @SQL );

收集sp_whoisactive的信息记录,也可以使用Insert Into命令,Insert Into <hist_table_name> Exec sp_whoisactive;。仍然推荐上面的方法。

如何查询sp_whoisactive的结果

下面只是一个入门查询。可以根据早些时候用户抱怨查询非常缓慢,来查看特定时间段的信息。比如,我(原作者)曾经使用 WhoIsActive 日志表来确定是谁导致 tempdb 变得异常大。当我找到它时,tempdb 的大小为 500GB!我将查询切换为包括 tempdb_allocations 和 tempdb_current 以及 ORDER BY tempdb_allocations DESC,这样就会很明显知道业务用户正在查询的所有事情。

SELECT TOP 1000 CPU, reads, collection_time, start_time, [dd hh:mm:ss.mss] AS 'run duration', [program_name], login_name, database_name, session_id, blocking_session_id, wait_info, sql_text, *
FROM WhoIsActive
WHERE collection_time BETWEEN '2016-07-20 07:55:00.000' AND '2016-07-20 09:00:00.000'
AND login_name NOT IN ('DomainName\sqlservice')
--AND CAST(sql_text AS varchar(max)) LIKE '%some query%'
ORDER BY 1 DESC

如何使用 sp_WhoIsActive 查找 SQL Server 慢查询

本部分建议直接参考How to Use sp_WhoIsActive to Find Slow SQL Server Queries原文。原文提供了脚本工具下载(下载的脚本有些长,可能无法介绍…),且有一个视频教程(需qiang)

DBA需要可以快速找到哪个查询和存储过程运行得比较慢。

sp_WhoIsActive有各种参数,但要知道,传入的参数越多,sp_WhoIsActive需要做的工作就越多,以便从 SQL Server 的动态管理视图 (DMV) 中获取想要的数据,运行速度也会越慢。

下面是几个很有用的参数:

  • @get_plans = 1 – 提供运行查询的执行计划。
  • @get_locks = 1 – 提供一个 XML 片段,可以单击以查看每个查询拥有哪些表、行、对象等锁。当试图找出某个查询阻止其他查询执行的原因时很有用。
  • @get_task_info = 2 – 如果一个查询并行进行,且你正在对 CXPACKET等待 (CXPACKET waits)进行故障排除,则可以找出查询中的每个任务正在等待什么。

SQLServer中sp_Who、sp_Who2和sp_WhoIsActive介绍和查看监视运行相关推荐

  1. sqlserver 中EXEC和sp_executesql使用介绍

    sqlserver 中EXEC和sp_executesql使用介绍 MSSQL为我们提供了两种动态运行SQL语句的命令,各自是EXEC和sp_executesql;通常,sp_executesql则更 ...

  2. SQLServer优化:SQLServer中NOLOCK关键字的用法介绍

    1.为什么SQLServer有NOLOCK关键字? SQLServer没创建一个查询,都相当于创建一个查询会话,在不同的查询分析器里面进行的查询操作,可能会影响别的查询会话.比较典型的一个例子,如果你 ...

  3. 知方可补不足~sqlserver中使用sp_who查看sql的进程

    回到目录 在SQLSERVER中每个会话,即每个查询分析器窗口都会产生一个SQL进程,对于那些持续时间短的进程,它们转瞬即失,而对于持续时间比较长的,我们需要希望查看它的运行状态,就可以借助SQL提供 ...

  4. 简单介绍SQLserver中的declare变量用法

    这篇文章主要介绍了SQLserver中的declare变量用法,sql中declare是声明的意思,就是声明变量的,这个一般是用在函数和存储过程中的.感兴趣的可以来了解一下 平时写SQL查询.存储过程 ...

  5. SQLServer中的死锁的介绍

    简介      什么是死锁? 我认为,死锁是由于两个对象在拥有一份资源的情况下申请另一份资源,而另一份资源恰好又是这两对象正持有的,导致两对象无法完成操作,且所持资源无法释放. 什么又是阻塞? 阻塞是 ...

  6. 数据库 SQLServer中GUID用法介绍

    数据库 SQLServer中GUID用法介绍 1.NEWID用法 NEWID()作用是生成无顺序的GUID字符串.用法如下: SELECT NEWID() --生成36位的GUID SELECT RE ...

  7. 数据库:SQLServer中GUID用法介绍

    今天给大家分享一下SQLServer中生成GUID的用法. 一.NEWID用法 NEWID()作用是生成无顺序的GUID字符串.用法如下: SELECT NEWID() --生成36位的GUIDSEL ...

  8. 关于Sqlserver中 BCP命令,实现数据导出功能。

    关于Sqlserver中 BCP命令,实现数据导出功能. exec master..xp_cmdshell 'bcp "select 账号 ,姓名, 账号 from datat.dbo.个人 ...

  9. Sqlserver中一直在用又经常被忽略的知识点一

    已经有快2个月没有更新博客了,实在是因为最近发生了太多的事情,辞了工作,在湘雅医院待了一个多月,然后又新换了工作...... 在平时的工作中,Sqlserver中许多知识点是经常用到的,但是有时候我们 ...

  10. 如何将oracle数据库中的表结构导入到sqlserver中,Oracle转换成SqlServer数据库的步骤...

    1 背景 ITM系统目前支持MysqL.Oracle数据库,由于现在需要和CA产品进行结合,用CA产品的采集功能进行数据采集,因此需要使用CA产品的sqlServer数据库,为了使得系统支持sqlse ...

最新文章

  1. JSP内置对象-application
  2. 从内存细看static
  3. 廊田镇楼下村定点帮扶-农业大健康·李喜贵:功能性农业深加工
  4. Android编译笔记之五
  5. DeepSORT多目标跟踪算法
  6. 软件构造 第五章第一节 可复用性的度量、形态和外部观察
  7. mysql proxy 主从_【MYSQL知识必知必会】MySQL主从复制读写分离(基于mysql-proxy实现)...
  8. [React] 尚硅谷 -- 学习笔记(七)
  9. SpringBoot集成Shiro进行权限控制和管理
  10. 自定义按键_NS推送10.0.0版本更新 新增按键自定义和数据转移功能
  11. 我,三十岁,还在做技术,被中年危机倒逼的程序员该何去何从?
  12. 公安交管网服务器维护,交管网总是维护
  13. 0-1背包问题-c语言实现
  14. robo3T篇 — robo3T的使用说明
  15. 拟合系数 / 决定系数 / R方 / R^2的理解
  16. 第四周项目2--建立”单链表“算法库
  17. 【Windows10】远程桌面共享多个显示屏
  18. cacti监控及配置
  19. 抖音推广——抖音吸粉技巧分享
  20. 名牌产品都在使用的公关策略

热门文章

  1. Sentaurus 入门之一安装教程
  2. 基于openflow的SDN技术
  3. QMC解码-某音乐解码
  4. STC单片机 EEPROM和低功耗笔记
  5. ipython安装报错无效_pip,IPython安装(Python2.7版本)windows环境和Linux环境
  6. Ipython安装错误集锦
  7. Linux-Shell脚本教学
  8. Linux Shell脚本教程(bash)
  9. Unity-VScode-Emmylua配置报错解决
  10. [Android][Kernel]基于crash工具搭建分析ramdump的平台