一、问题背景:不寻常的CPU告警
近日,一位在医院工作的朋友找到,说他们核心HIS系统的CPU使用率突然攀升至40%,而历史水平一直在20%左右,希望能帮忙排查。凭借经验,判断这很可能是一个典型的SQL性能问题。
果不其然,从分析到解决,整个过程不到10分钟。本文将完整复盘分析思路,希望能为大家提供一个高CPU消耗场景下的性能优化实战参考。
二、性能诊断
2.1 定位CPU消耗来源
接到问题后,首先请朋友帮忙执行top
命令,获取CPU使用率的详细分解。单纯一个“40%”的指标过于笼统,我们需要深入分析CPU时间的具体去向。
Cpu(s): 45.3%us, 2.5%sy, 0.0%ni, 50.8%id, 1.1%wa, 0.0%hi, 0.3%si, 0.0%st
我们重点关注以下三项:
us
(user space):用户空间程序占用的CPU百分比。在我们的场景中,这主要指向Oracle数据库进程。sy
(system space):内核空间占用的CPU百分比,通常为操作系统内核、驱动等消耗。wa
(I/O wait):CPU等待I/O操作完成的时间百分比。
从top
的输出可以看到,用户空间(us)占用了高达45.3%的CPU,而系统内核(sy)和IO等待(wa)的占比都非常低。这清晰地表明:系统的IO性能没有瓶颈,问题根源在于Oracle数据库自身消耗了过多的CPU资源。
那么,什么情况下Oracle会消耗大量CPU而IO压力不大呢?常见原因包括:
- 密集的内存运算:如大量的逻辑读(Logical Reads)、复杂的函数或表达式计算、高频的Mutex/Latch争用等。
- 低效的程序代码:如循环嵌套、无谓计算的PL/SQL或Java存储过程。
- 特定内部功能:如Oracle的In-Memory (IM) Columnar Store等。
在当前大内存服务器普及的背景下,这种“高CPU、低IO”的性能问题正变得越来越普遍。
2.2 锁定问题SQL
明确了方向后,我让朋友运行诊断脚本,重点关注处于ON CPU
状态的会话及其执行的SQL。很快,我们就锁定了罪魁祸首,并通过关联v$active_se