天天看点

关于CPU使用率高的awr分析

今天看到一个报警信息,大体是CPU使用异常。

ZABBIX-监控系统:

------------------------------------

报警内容: CPU utilization is too high

报警级别: PROBLEM

监控项目: CPU idle time:55.17 %

报警时间:2016.03.22-19:03:23

对于这个问题,看到CPU使用率过高,大体已经有了一些思路。但是还是需要一些论证。

首先查看sar的情况,可以看出CPU的平均使用率在30~40%

06:55:01 PM       all     32.35      0.00      7.57      0.00     60.08

06:56:01 PM       all     31.78      0.00      7.55      0.00     60.67

06:57:01 PM       all     31.65      0.00      7.52      0.01     60.82

06:58:01 PM       all     31.42      0.00      7.48      0.00     61.10

06:59:01 PM       all     30.91      0.00      7.58      0.00     61.51

07:00:02 PM       all     31.13      0.00      7.62      0.00     61.25

07:01:01 PM       all     30.84      0.00      7.62      0.02     61.53

07:02:01 PM       all     31.86      0.00      7.83      0.11     60.19

07:03:01 PM       all     32.88      0.00      7.64      0.06     59.43

Average:          all     24.34      0.00      7.11      0.04     68.51

但是top的结果却让我有些奇怪。

top - 19:04:19 up 68 days, 22:47,  2 users,  load average: 4.47, 4.58, 4.47

Tasks: 284 total,  14 running, 269 sleeping,   0 stopped,   1 zombie

Cpu(s): 31.6% us,  3.9% sy,  0.0% ni, 60.5% id,  0.0% wa,  0.1% hi,  3.9% si

Mem:  16430192k total, 16283948k used,   146244k free,   123716k buffers

Swap: 33551744k total,   115632k used, 33436112k free, 13809040k cached

可以看到CPU的使用率虽高,但是IO却几乎没有什么消耗。

然后查看部分的进程信息,发现有部分的进程CPU使用率较高。这个时候看起来是一个全表扫描的概率偏大了。

PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+ 

COMMAND                                                                

28185

oracle    16   0 6282m 835m 829m S 82.6  5.2   5:01.48 oracletest

(LOCAL=NO)                                                  

28237

oracle    16   0 6282m 832m 826m S 82.6  5.2   4:50.64 oracletest

28345

oracle    16   0 6283m 874m 867m R 82.6  5.5   3:54.84 oracletest

28425

oracle    16   0 6281m 689m 682m S 82.6  4.3   3:50.17 oracletest

28703 oracle    16   0 6281m 571m 565m S 82.6  3.6   2:06.54 oracletest (LOCAL=NO)  

然后绑定进程,查看进程对应的session执行sql的情况,发现语句竟然是一句非常简单的查询。

PREV_SQL_ID                    SQL_TEXT

------------------------------ ------------------------------------------------------------

7gwxpwru0czqw                  select companyname from license   

执行计划如何呢,确实是一个全表扫描。

Plan hash value: 2492423498

-----------------------------------------------------------------------------

| Id  | Operation         | Name    | Rows  | Bytes | Cost (%CPU)| Time     |

|   0 | SELECT STATEMENT  |         |       |       |     3 (100)|          |

|   1 |  TABLE ACCESS FULL| LICENSE |     1 |    29 |     3   (0)| 00:00:01 |

但是这个时候的问题倒不是在于这个全表扫描了,关键就是这个表中目前只有1条数据。

为什么会有这个CPU消耗较大的情况呢,目前来看,语句的执行频率极高。

Per Second

Per Transaction

Redo size:

3,455.88

0.53

Logical reads:

54,200.78

8.32

Block changes:

17.89

0.00

Physical reads:

5.72

Physical writes:

1.25

User calls:

39,104.93

6.01

Parses:

13,033.74

2.00

Hard parses:

4.75

Sorts:

12.16

Logons:

0.07

Executes:

13,035.13

Transactions:

6,512.05

如果看到这种情况,会发现目前的系统还是非常繁忙的,那么主要在哪儿忙呢。可以看到rollback的比例非常高。

% Blocks changed per Read:

0.03

Recursive Call %:

25.04

Rollback per transaction %:

99.97

Rows per Sort:

2027.20

从这个也可以看出应该是应用的逻辑部分出了问题,或者数据问题导致的校验失败导致回滚。

这个时候查看等待事件的情况如下。

Event

Waits

Time(s)

Avg Wait(ms)

% Total Call Time

Wait Class

CPU time

10,839

100.1

SQL*Net message to client

93,924,202

73

.7

Network

latch: cache buffers chains

79,297

8

.1

Concurrency

cursor: pin S

71,807

Other

log file sync

7,136

1

Commit

我们直接到sql的部分来看看。下面两条语句的执行频率极高,大概是1个小时2千多万次的频率。

Elapsed Time (s)

CPU Time (s)

Executions

Elap per Exec (s)

% Total DB Time

SQL Id

SQL Module

SQL Text

1,470

1,414

23,451,700

13.57

<a href="#7gwxpwru0czqw">7gwxpwru0czqw</a>

JDBC Thin Client

select companyname from licens...

694

686

23,024,521

6.41

<a href="#7nkxbfnwgx93v">7nkxbfnwgx93v</a>

select supdepid from mdepart...

那么怎么看出语句存在问题呢。可以在executions部分找到一些痕迹。

Rows Processed

Rows per Exec

CPU per Exec (s)

23,440,315

select supdepid from mdepart

第二条语句的执行频率和第一条一样都非常高,但是第二条语句的“Rows Processed"为0

如果查看语句的buffer gets,就会发现是0

$ sh showsql.sh 7nkxbfnwgx93v

HASH_VALUE PLAN_HASH_VALUE DISK_READS BUFFER_GETS      SORTS EXECUTIONS   CPU_TIME ELAPSED_TIME_S WAIT_TIME_EACH

---------- --------------- ---------- ----------- ---------- ---------- ---------- -------------- --------------

 956212347      3350531500          0           0          0 1806030210         29              0              2

这是为什么呢。因为语句是这样的形式。

select supdepid from mdepartment where id =''

其中这个表的id列有非空约束,还有对应的id索引,这种情况下,直接会返回0行,尽管这个表里有百万的数据。

所以从这些痕迹来看,这个问题是一个异常的状态,需要和开发人员协调,到底是数据问题还是调用的逻辑部分出了问题。