最近一个客户抱怨他的核心EBS数据库出现性能问题。这是一个10.2.0.3的数据库,
运行在Red Hat Enterprise Linux Server release 5.5 (Linux x86-64)操作系统上。

根据客户描述,由于需要维护UPS,他们重启了数据库,结果重启数据库后他们发现只要他们的应用
开始连接数据库,那么主机的sys CPU使用率就会变成100%, 但是user CPU使用率几乎是0.
而且只要停掉监听或者应用不开启新session连接数据库,这个问题就会消失。

如下是问题发生期间的vmstat输出,可见cpu中的sys(倒数第4列)几乎100%, CPU Run Queue (第1列)
非常高,而此时free memory还有20G(第4列),看来内存很充裕。

SNAP_INTERVAL 15
CPU_COUNT 32

zzz ***Fri Dec 2 17:05:03 CST 2016
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
48  0      0 22026868 213392 37138888    0    0    21    31   13   39  6  8 86  0  0
44  1      0 21968452 213392 37138900    0    0     0   360 1093  537  8 92  0  0  0
44  1      0 21941632 213392 37139028    0    0     0   288 1080  371  9 91  0  0  0
......
zzz ***Fri Dec 2 17:10:12 CST 2016
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
121  2      0 21495944 218356 37142412    0    0    21    31   13   39  6  9 85  0  0
122  4      0 21486192 218356 37142432    0    0     0   308  119  753  7 93  0  0  0
121  2      0 21478868 218364 37142424    0    0     0   592   97  517  5 95  0  0  0

首先我看了一遍客户提供的AWR,发现DB相当空闲,虽然CPU time占据了91.2,但是总的CPU Time
在119分钟的采样中只有18345秒(305分钟),相对于客户32个CPU Core来说不是个问题。

Snap Id Snap Time Sessions Cursors/Session
Begin Snap: 38119 02-Dec-16 16:00:28 255 63.2
End Snap: 38121 02-Dec-16 18:00:18 193 48.7
Elapsed: 119.83 (mins)
DB Time: 335.30 (mins)  <<< 相当空闲

Top 5 Timed Events

Event    Waits    Time(s)    Avg Wait(ms)    % Total Call Time    Wait Class
CPU time         18,345         91.2    
os thread startup    971    937    965    4.7    Concurrency
latch free    582    657    1,128    3.3    Other
db file sequential read    4,712,799    345    0    1.7    User I/O
log file parallel write    247,562    258    1    1.3    System I/O

AWR中没发现什么异常,DB的alert log显示一些无法fork进程的消息,估计是资源紧张了。

Fri Dec  2 17:06:16 2016
Process q002 died, see its trace file
Fri Dec  2 17:06:16 2016
ksvcreate: Process(q002) creation failed

好吧,一般情况下如果我们发现CPU高,无论是sys的还是user的,我们一般的做法是先定位top function call
然后通过这些function call来定位oracle或者OS行为,并且通过这些call来搜索与匹配已知问题。
在linux上,最方便收集这些信息的就是用perf这个工具。关于perf,参见:

https://perf.wiki.kernel.org/index.php/Tutorial

结果客户说他们无法安装perf命令,不过他提到他的OS中显示很多错误:

Dec  2 17:05:23 erpdb1 kernel: BUG: soft lockup - CPU#5 stuck for 10s! [oracle:15668]
Dec  2 17:05:23 erpdb1 kernel: CPU 5:
Dec  2 17:05:23 erpdb1 kernel: Call Trace:
Dec  2 17:05:23 erpdb1 kernel:  [<ffffffff8000e9a8>] __set_page_dirty_nobuffers+0xc2/0xe9
Dec  2 17:05:23 erpdb1 kernel:  [<ffffffff80007c1b>] unmap_vmas+0x522/0x904
Dec  2 17:05:23 erpdb1 kernel:  [<ffffffff80012d08>] unmap_region+0xb8/0x12b
Dec  2 17:05:23 erpdb1 kernel:  [<ffffffff80011e45>] do_munmap+0x21b/0x29a
Dec  2 17:05:23 erpdb1 kernel:  [<ffffffff800655ab>] __down_write_nested+0x12/0x92
Dec  2 17:05:23 erpdb1 kernel:  [<ffffffff80121e88>] sys_shmdt+0x5b/0x133
Dec  2 17:05:23 erpdb1 kernel:  [<ffffffff8005e28d>] tracesys+0xd5/0xe0

通过call stack,看来在回收内存时报错了,推测这个错误应当发生在进程退出阶段,
不过难以断定这些错误与sys cpu高的因果关系。

结合客户描述的现象,这看起来很像连接风暴,因此我们检查了ps的输出,发现进程数并未明显增加,
不过问题最严重的时间断片了。这些零碎的信息并不能给我们一个很清晰的线索。

$ awk '/$ORACLE_SID/{n++;next}/^zzz/{if(t)print t,"-",n;t=$0;n=0}END{print t,"-",n}' XXXX_ps_16.12.02.1700.dat

zzz ***Fri Dec 2 17:04:18 CST 2016 - 235
zzz ***Fri Dec 2 17:04:33 CST 2016 - 236
zzz ***Fri Dec 2 17:04:48 CST 2016 - 229
zzz ***Fri Dec 2 17:05:03 CST 2016 - 228   <<<< 此时问题实际上已经发生了
zzz ***Fri Dec 2 17:05:19 CST 2016 - 178   <<<< 17:05 ~ 17:13 的断片了
zzz ***Fri Dec 2 17:13:19 CST 2016 - 283   <<<<
zzz ***Fri Dec 2 17:13:34 CST 2016 - 283
zzz ***Fri Dec 2 17:13:49 CST 2016 - 196

接下来看了top,发现虽然OS的sys CPU高,不过top的process都是oracle,表明此问题一定
与oracle有点关系。

zzz ***Fri Dec 2 17:05:03 CST 2016
top - 17:05:05 up  9:24,  3 users,  load average: 41.76, 28.54, 19.68
Tasks: 660 total,  45 running, 615 sleeping,   0 stopped,   0 zombie
Cpu(s):  8.3%us, 91.7%sy,  0.0%ni,  0.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  65993408k total, 44046040k used, 21947368k free,   213392k buffers
Swap: 62918564k total,        0k used, 62918564k free, 37139028k cached

PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
19610 oracle   25   0 9917m 8.5g 8.5g R 101.8 13.6   1:19.76 oracle
19756 oracle   25   0 9917m 7.0g 7.0g R 100.9 11.1   1:05.76 oracle
19760 oracle   25   0 9917m 6.7g 6.7g R 100.9 10.7   1:06.56 oracle
19942 oracle   25   0 9917m 5.1g 5.1g R 100.9  8.0   0:46.67 oracle
20107 oracle   25   0 9917m 3.1g 3.1g R 100.9  4.9   0:26.39 oracle
20204 oracle   25   0 9917m 1.2g 1.2g R 100.9  1.9   0:10.63 oracle
19486 oracle   25   0 9917m 9.3g 9.3g R 99.9 14.8   1:25.10 oracle
19721 oracle   25   0 9917m 6.9g 6.8g R 99.9 10.9   1:08.22 oracle

那么问题来了,oracle软件一般都是执行user code,因此大多数情况下会消耗user space
的CPU,怎么会消耗sys CPU呢? 先man一下top:

sy - This is the amount of time that the CPU spent running the kernel.
All the processes and system resources are handled by the Linux kernel.
When a user space process needs something from the system, for example
when it needs to allocate memory, perform some I/O, or it needs to
create a child process, then the kernel is running.

这说明oracle进程是有可能消耗kernel space的CPU的,比如申请内存,执行I/O等。
挑出上面的top列出的进程,在ps输出中找规律:

$ grep 19610 Dec*
TIME           USER       PID  PPID PRI %CPU %MEM    VSZ   RSS WCHAN  S  STARTED     TIME COMMAND
Dec 2 17:03:17 oracle  19610     1  14 78.5  0.9 10155628 605564 -   R 17:03:10 00:00:05 ora_q002_XXXX
Dec 2 17:03:32 oracle  19610     1  14 57.6  2.1 10155628 1437940 -  R 17:03:09 00:00:13 ora_q002_XXXX
Dec 2 17:03:47 oracle  19610     1  14 67.6  4.3 10155628 2868692 -  R 17:03:10 00:00:25 ora_q002_XXXX
Dec 2 17:04:02 oracle  19610     1  14 75.8  6.9 10155628 4559708 -  R 17:03:09 00:00:40 ora_q002_XXXX
Dec 2 17:04:18 oracle  19610     1  14 76.7  9.1 10155628 6015688 -  R 17:03:10 00:00:52 ora_q002_XXXX
Dec 2 17:04:33 oracle  19610     1  14 70.9 10.4 10155628 6865876 -  R 17:03:09 00:00:59 ora_q002_XXXX
Dec 2 17:04:48 oracle  19610     1  14 67.7 11.6 10155628 7684088 -  R 17:03:09 00:01:07 ora_q002_XXXX
Dec 2 17:05:03 oracle  19610     1  14 68.9 13.3 10155628 8838576 -  R 17:03:10 00:01:18 ora_q002_XXXX

$ grep 19756 Dec*

TIME           USER       PID  PPID PRI %CPU %MEM    VSZ   RSS WCHAN  S  STARTED     TIME COMMAND
Dec 2 17:03:47 oracle  19756     1  16 50.0  0.3 10155628 222508 -   R 17:03:44 00:00:02 oracleXXXX (LOCAL=NO)
Dec 2 17:04:02 oracle  19756     1  14 47.9  1.4 10155628 961764 -   R 17:03:43 00:00:09 oracleXXXX (LOCAL=NO)
Dec 2 17:04:18 oracle  19756     1  14 55.5  3.0 10155628 2021664 -  R 17:03:44 00:00:18 oracleXXXX (LOCAL=NO)
Dec 2 17:04:33 oracle  19756     1  14 68.4  5.6 10155628 3703572 -  R 17:03:43 00:00:34 oracleXXXX (LOCAL=NO)
Dec 2 17:04:48 oracle  19756     1  14 75.4  8.2 10155628 5459948 -  R 17:03:43 00:00:49 oracleXXXX (LOCAL=NO)
Dec 2 17:05:03 oracle  19756     1  14 80.6 10.9 10155628 7217680 -  R 17:03:44 00:01:04 oracleXXXX (LOCAL=NO)

从以上输出可以发现一个明显规律: 这些进程的RSS在1分多钟从几十M变成7~8G,但是VSZ却没有变化。
接着man ps

VSZ: virtual memory usage of entire process. vm_lib + vm_exe + vm_data + vm_stack
RSS: resident set size, the non-swapped physical memory that a task has used (in kiloBytes). (alias rssize, rsz).

任何一个oracle进程的VSZ约等于SGA加上这个进程的PGA(实际上VSZ还包含一些kernel内存),正常情况下一个进程的pga是很小的。
以上输出中VSZ没有改变,因此发生巨大变化的RSS申请的内存一定不是PGA而是SGA(因为如果增长的是PAG那么VSZ也会跟着增长)。
好吧,那么只有一个可能了,那就是这个进程在touch整个sga,为什么会这样?

我们需要再回到原点再看一眼AWR的数据库参数信息,赫然发现如下内容:

sga_max_size    10250878976
sga_target    8304721920
pre_page_sga    TRUE  <<<< 看这里

这个设置中的sga_max_size正好10g,与我们在ps中看到的VSZ正好相等。

问题的原因是客户设置了pre_page_sga=true,这样在oracle进程启动阶段会touch整个SGA,
这个过程中会调用OS的sys call来touch 整个 shared memory entry,因此引发了高SYS CPU消耗。
参见如下文档的描述:

Health Check Alert: Consider setting PRE_PAGE_SGA to FALSE (Doc ID 957525.1)

回过头来再看alert log,观察参数pre_page_sga是什么时候改的,发现它在很久以前的很多次重启就是true了。
也就是说,这个问题一直都存在,只是客户最近维护UPS之后才发现,维护UPS这个信息误导了我们。

关于sys CPU usage 100%问题的分析的更多相关文章

  1. mysql cpu 100% 满 优化方案 解决MySQL CPU占用100%的经验总结

    下面是一些经验 供参考 解决MySQL CPU占用100%的经验总结 - karl_han的专栏 - CSDN博客 https://blog.csdn.net/karl_han/article/det ...

  2. Linux jstack分析cpu占用100%

    背景: 运行测试程序后,top命令发现某个进程(pid)占用cpu达到100%.   查看哪个线程占用最多资源: ps mp pid -o THREAD,tid,命令查看这个进程下面的所有线程占用情况 ...

  3. PostgreSQL CPU满(100%)性能分析及优化(转)

    PostgreSQL CPU满(100%)性能分析及优化 转自:https://help.aliyun.com/knowledge_detail/43562.html    在数据库运维当中,一个DB ...

  4. MySQL SYS CPU高的案例分析(二)

    原文:MySQL SYS CPU高的案例分析(二) 后面又做了补充测试,增加了每秒context switch的监控,以及SQL执行时各步骤消耗时间的监控. [测试现象一] 启用1000个并发线程的压 ...

  5. MySQL SYS CPU高的案例分析(一)

    原文:MySQL SYS CPU高的案例分析(一) [现象] 最近关注MySQL CPU告警的问题时,发现有一种场景,有一些服务器最近都较频繁的出现CPU告警,其中的现象是 SYS CPU占比较高. ...

  6. Docker CPU Usage

    背景 当一台机器上跑有多个 Docker Container 的时候,我们需要知道,哪些容器占用了多少资源.采集这些指标,来让我们可以更加好的分配资源给每个 Container. 获取容器CPU使用率 ...

  7. 一条语句导致CPU持续100%

    一大早收到一堆CPU预警邮件,通常每天只在统计作业执行期间会收到2~3封CPU预警邮件.这次的预警来自另一台服务器,并且明细数据显示其CPU一直维持在49%.登录到服务器,查看任务管理器(查看资源监视 ...

  8. CPU利用率和CPU负荷(CPU usage vs CPU load)

    对于CPU的性能监测,通常用top指令能显示出两个指标:cpu 利用率和cpu负荷. 其中%Cpu相关的内容: us表示用户进程cpu利用率,sy表示系统内核进程cpu利用率,ni表示运行正常进程消耗 ...

  9. 【故障公告】数据库服务器 CPU 近 100% 引发的故障(源于 .NET Core 3.0 的一个 bug)

    非常抱歉,这次故障给您带来麻烦了,请您谅解. 今天早上 10:54 左右,我们所使用的数据库服务(阿里云 RDS 实例 SQL Server 2016 标准版)CPU 突然飙升至 90% 以上,应用日 ...

随机推荐

  1. PMP备考指南之第一章:引论

    本文已同步至 GitHub/Gitee/公众号,感兴趣的同学帮忙点波关注~ 第一章  引论 1."项目管理知识体系":应该包含所有行业.应用领域项目管理的具体知识.技能.方法和实践 ...

  2. protocol buffers生成go代码原理

    本文描述了protocol buffers使用.proto文件生成pb.go文件的过程 编译器 编译器需要插件来编译环境,使用如下方式安装插件:go get github.com/golang/pro ...

  3. GDAL并行I/O

    和导师在Transactions in GIS 上发表的关GDAL并行I/O方面的文章(SSCI, IF=0.906)http://onlinelibrary.wiley.com/doi/10.111 ...

  4. redis实战笔记(4)-第4章 数据安全与性能保障

    本章主要内容 4.1 将数据持久化至硬盘 4.2 将数据复制至其他机器 4.3 处理系统故障 4.4 Redis事务 4.5 非事务型流水线( non-transactional pipeline) ...

  5. for循环-鼠标移入事件

    这里当鼠标移入触发事件时候,会报错,为什么呢?注意一下objs数组的长度是5. 因为在鼠标移入事件触发之前for循环已经将i变成5,objs[5]是不存在的,所以会报错. 可以用this来解决这种问题 ...

  6. [codeup] 1128 出租车费

    题目描述 某市出租车计价规则如下:起步4公里10元,即使你的行程没超过4公里:接下来的4公里,每公里2元:之后每公里2.4元.行程的最后一段即使不到1公里,也当作1公里计费. 一个乘客可以根据行程公里 ...

  7. 基于python的多线程暴破脚本

    搭建了一个本地wordpress,写一个基于多线程异步I/O的暴力破解 1 测试 提交错误的表单数据时,查看请求参数 登录时发送的cookie 2 登录分析 经过多次测试,发现无论是输入正确的密码还是 ...

  8. 未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序的解决方法

    在win7 操作系统中SQL2008导入excel2007 出现: 未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序 的解决方法: 出现这个原因是office 2007 ...

  9. JavaScript unshift()函数移入数据到数组第一位

    你不仅可以 shift(移出)数组中的第一个元素,你也可以 unshift(移入)一个元素到数组的头部. .unshift() 函数用起来就像 .push() 函数一样, 但不是在数组的末尾添加元素, ...

  10. Struts初始

    1.首先我们先创建一个maven的简单工程, 如图 然后点击创建一个简单的工程,点击下一步, 然后, 再次输入工程的各项信息,1组织名,2.项目名称,版本名,一般为默认,3,jar包暂时默认,当前的j ...