SQLSERVER排查CPU占用高的情况

转载 2016年08月30日 19:43:59

SQLSERVER排查CPU占用高的情况

今天中午,有朋友叫我帮他看一下数据库,操作系统是Windows2008R2 ,数据库是SQL2008R2 64位

64G内存,16核CPU

硬件配置还是比较高的,他说服务器运行的是金蝶K3软件,数据库实例里有多个数据库

 

现象

他说是这几天才出现的,而且在每天的某一个时间段才会出现CPU占用高的情况

内存占用不太高,只占用了30个G

CPU占用100%


排查方向

 

一般排查都是用下面的脚本,一般会用到三个视图sys.sysprocesses ,dm_exec_sessions ,dm_exec_requests

1 USE master
2 GO
3 --如果要指定数据库就把注释去掉
4 SELECT * FROM sys.[sysprocesses] WHERE [spid]>50 --AND DB_NAME([dbid])='gposdb'
5 SELECT COUNT(*) FROM [sys].[dm_exec_sessions] WHERE [session_id]>50

看一下当前的数据库用户连接有多少

然后使用下面语句看一下各项指标是否正常,是否有阻塞,这个语句选取了前10个最耗CPU时间的会话

 1 SELECT TOP 10
 2 [session_id],
 3 [request_id],
 4 [start_time] AS '开始时间',
 5 [status] AS '状态',
 6 [command] AS '命令',
 7 dest.[text] AS 'sql语句', 
 8 DB_NAME([database_id]) AS '数据库名',
 9 [blocking_session_id] AS '正在阻塞其他会话的会话ID',
10 [wait_type] AS '等待资源类型',
11 [wait_time] AS '等待时间',
12 [wait_resource] AS '等待的资源',
13 [reads] AS '物理读次数',
14 [writes] AS '写次数',
15 [logical_reads] AS '逻辑读次数',
16 [row_count] AS '返回结果行数'
17 FROM sys.[dm_exec_requests] AS der 
18 CROSS APPLY 
19 sys.[dm_exec_sql_text](der.[sql_handle]) AS dest 
20 WHERE [session_id]>50 AND DB_NAME(der.[database_id])='gposdb'  
21 ORDER BY [cpu_time] DESC


如果想看具体的SQL语句可以执行下面的SQL语句,记得在SSMS里选择以文本格式显示结果

1 --在SSMS里选择以文本格式显示结果
2 SELECT TOP 10 
3 dest.[text] AS 'sql语句'
4 FROM sys.[dm_exec_requests] AS der 
5 CROSS APPLY 
6 sys.[dm_exec_sql_text](der.[sql_handle]) AS dest 
7 WHERE [session_id]>50  
8 ORDER BY [cpu_time] DESC

模拟了一些耗CPU时间的动作

 

还有查看CPU数和user scheduler数和最大工作线程数,检查worker是否用完也可以排查CPU占用情况

1 --查看CPU数和user scheduler数目
2 SELECT cpu_count,scheduler_count FROM sys.dm_os_sys_info
3 --查看最大工作线程数
4 SELECT max_workers_count FROM sys.dm_os_sys_info

查看机器上的所有schedulers包括user 和system
通过下面语句可以看到worker是否用完,当达到最大线程数的时候就要检查blocking了


对照下面这个表
各种CPU和SQLSERVER版本组合自动配置的最大工作线程数
CPU数                 32位计算机                        64位计算机
<=4                     256                                   512
  8                        288                                   576
 16                       352                                   704
 32                       480                                   960

1 SELECT
2 scheduler_address,
3 scheduler_id,
4 cpu_id,
5 status,
6 current_tasks_count,
7 current_workers_count,active_workers_count
8 FROM sys.dm_os_schedulers

 

如果SQLSERVER存在要等待的资源,那么执行下面语句就会显示出会话中有多少个worker在等待

结合[sys].[dm_os_wait_stats]视图,如果当前SQLSERVER里面没有任何等待资源,那么下面的SQL语句不会显示任何结果

 1 SELECT TOP 10
 2  [session_id],
 3  [request_id],
 4  [start_time] AS '开始时间',
 5  [status] AS '状态',
 6  [command] AS '命令',
 7  dest.[text] AS 'sql语句', 
 8  DB_NAME([database_id]) AS '数据库名',
 9  [blocking_session_id] AS '正在阻塞其他会话的会话ID',
10  der.[wait_type] AS '等待资源类型',
11  [wait_time] AS '等待时间',
12  [wait_resource] AS '等待的资源',
13  [dows].[waiting_tasks_count] AS '当前正在进行等待的任务数',
14  [reads] AS '物理读次数',
15  [writes] AS '写次数',
16  [logical_reads] AS '逻辑读次数',
17  [row_count] AS '返回结果行数'
18  FROM sys.[dm_exec_requests] AS der 
19  INNER JOIN [sys].[dm_os_wait_stats] AS dows 
20  ON der.[wait_type]=[dows].[wait_type]
21  CROSS APPLY 
22  sys.[dm_exec_sql_text](der.[sql_handle]) AS dest 
23  WHERE [session_id]>50  
24  ORDER BY [cpu_time] DESC

比如我当前执行了查询SalesOrderDetail_test表100次,由于表数据非常多,所以SSMS需要把SQLSERVER执行的结果慢慢的取走,

造成了ASYNC_NETWORK_IO等待

1 USE [AdventureWorks]
2 GO
3 SELECT * FROM dbo.[SalesOrderDetail_test]
4 GO 100

 


问题源头

经过排查和这几天的观察情况,确定是某些表缺失索引导致,现在在这些表上增加了索引,问题解决

1 select * from t_AccessControl        --权限控制表权限控制
2 select * from t_GroupAccess            --用户组权限表用户组权限
3 select * from t_GroupAccessType        --用户组权限类表用户组权限类
4 select * from t_ObjectAccess        --对象权限表对象权限
5 select * from t_ObjectAccessType    --对象权限类型表对象权限类型
6 select * from t_ObjectType            --对象类型表对象类型

查询CPU占用高的语句

 1 SELECT TOP 10
 2    total_worker_time/execution_count AS avg_cpu_cost, plan_handle,
 3    execution_count,
 4    (SELECT SUBSTRING(text, statement_start_offset/2 + 1,
 5       (CASE WHEN statement_end_offset = -1
 6          THEN LEN(CONVERT(nvarchar(max), text)) * 2
 7          ELSE statement_end_offset
 8       END - statement_start_offset)/2)
 9    FROM sys.dm_exec_sql_text(sql_handle)) AS query_text
10 FROM sys.dm_exec_query_stats
11 ORDER BY [avg_cpu_cost] DESC

查询缺失索引

1 SELECT 
2     DatabaseName = DB_NAME(database_id)
3     ,[Number Indexes Missing] = count(*) 
4 FROM sys.dm_db_missing_index_details
5 GROUP BY DB_NAME(database_id)
6 ORDER BY 2 DESC;
 1 SELECT  TOP 10 
 2         [Total Cost]  = ROUND(avg_total_user_cost * avg_user_impact * (user_seeks + user_scans),0) 
 3         , avg_user_impact
 4         , TableName = statement
 5         , [EqualityUsage] = equality_columns 
 6         , [InequalityUsage] = inequality_columns
 7         , [Include Cloumns] = included_columns
 8 FROM        sys.dm_db_missing_index_groups g 
 9 INNER JOIN    sys.dm_db_missing_index_group_stats s 
10        ON s.group_handle = g.index_group_handle 
11 INNER JOIN    sys.dm_db_missing_index_details d 
12        ON d.index_handle = g.index_handle
13 ORDER BY [Total Cost] DESC;

定位问题后,新建非聚集索引

1 CREATE NONCLUSTERED INDEX IX_t_AccessControl_F4 ON dbo.t_AccessControl
2 (
3     FObjectType
4 )include([FUserID], [FAccessType], [FAccessMask]) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
5 GO
6 
7 drop index IX_t_AccessControl_F4 on t_AccessControl

 CPU占用恢复正常

跟踪模板和跟踪文件下载,请使用SQL2008R2 版本:files.cnblogs.com/lyhabc/跟踪模板和trace.rar

 


总结

从多次历史经验来看,如果CPU负载持续很高,但内存和IO都还好的话,这种情况下,首先想到的一定是索引问题,十有八九错不了。

注意文章开头贴出的客户机器负载情况图

 



http://www.cnblogs.com/lyhabc/archive/2013/06/12/3133273.html

Linux环境mysql cpu过高问题排查

Linux环境mysql cpu过高问题排查今早同事说系统很卡,自己操作了一下,确实变的很慢,登录mysql客户端,统计了一下客户调用返回速度,比预期慢了三倍,于是排查开始:思路 首先登录服务器,...
  • sh1747665463
  • sh1747665463
  • 2017年09月18日 15:40
  • 266

SQLSERVER排查CPU占用高的情况

今天中午,有朋友叫我帮他看一下数据库,操作系统是Windows2008R2 ,数据库是SQL2008R2 64位 64G内存,16核CPU 硬件配置还是比较高的,他说服务器运行的是金蝶K3软件,数...
  • thy822
  • thy822
  • 2013年10月23日 17:15
  • 772

【SQLSERVER】排查CPU占用高的情况

学习地址:http://www.cnblogs.com/lyhabc/archive/2013/06/12/3133273.html#top
  • zouxiongqqq
  • zouxiongqqq
  • 2014年07月01日 08:48
  • 295

进程cpu过高问题排查

一,结合linux基本命令和jmap,jstack等工具。  根据top命令,发现PID为28555的Java进程占用CPU高达200%,出现故障。   通过ps aux | grep P...
  • fcc7619666
  • fcc7619666
  • 2016年07月05日 11:27
  • 899

java进程CPU过高问题如何排查?

生产环境有时会遇到java进程CPU使用超过100%,遇到这种问题如何定位问题原因呢? 一般JAVA进程CPU过高主要是程序中出现了死循环,死循环会导致两种情况:第一种,死循环本身不需要耗费太多C...
  • zhouree
  • zhouree
  • 2015年04月20日 17:50
  • 1517

线上java程序CPU占用过高问题排查

工作中负责的有一个项目是使用iReport+JasperReport实现的一个打印系统。最近这个线上程序经常无响应,重启后恢复正常,但是时不时还是会出现类似的问题。 最后发现是Jaspe...
  • u010862794
  • u010862794
  • 2017年09月18日 16:01
  • 1945

jvm cpu过高排查实战

双十一了,头一天晚上10点左右收到阿里云cpu超过90%短信报警。 第二天上班了,开始处理,步骤如下: 1、top找出cpu高的java进程号9592 2、top -Hp  9592查看cpu占用ti...
  • yx511500623
  • yx511500623
  • 2016年11月11日 10:57
  • 1077

JVM CPU高负载的排查办法

今天线上一个tomcat进程cpu负载100%。按以下步骤查出原因。     1.执行top -c命令,找到cpu最高的进程的id     2.执行top -H -p pid,这个命令就能显示刚刚找到...
  • bruce128
  • bruce128
  • 2015年02月05日 20:17
  • 4284

SQLServer 定位CPU使用较高的用户和SQL

CPU 高的时候有很多方法定位,以下是一种比较慢的定位方法,不过本人也不会这样跟踪。实例如下: 首先确认高CPU是数据库内部消耗还是Windows其他应用程序消耗较高CPU。打开Windows 任...
  • kk185800961
  • kk185800961
  • 2015年12月03日 12:23
  • 1064

(一)JAVA CPU占用过高问题排查(linux)

JAVA CPU占用过高问题排查(linux) 最近发现有一个服务在服务器上无响应,到服务器上一看,好家伙,java进程CPU一直100%以上 简单记录下我对这个问题的跟踪 首先当然要看...
  • whupanyinghua
  • whupanyinghua
  • 2016年06月12日 23:47
  • 5399
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:SQLSERVER排查CPU占用高的情况
举报原因:
原因补充:

(最多只允许输入30个字)