AWR中CPU Time超100%非bug,是因DB CPU按多核CPU秒累加(如48核×1秒=48秒),而DB Time为单一时钟流逝时间(如40秒),故48/40=120%合理;12c因默认并行增强、多核普及更易显现。
AWR里CPU Time超过100%不是bug,是设计使然
oracle 12c awr报告中出现 cpu time 占比 105%、112% 甚至更高,不代表监控失准或系统异常。这是 time model 统计机制与底层系统调用差异导致的必然现象,从 10g 起就存在,12c 只是更常暴露出来——尤其在高并发、多核服务器上。
关键点在于:CPU Time 来自 v$sys_time_model 中的 DB CPU 累积值,它调用的是 getrusage();而总耗时基准 DB Time 来自 gettimeofday()。前者按每个 Oracle 进程实际消耗的 CPU 时间累加(可跨核并行),后者是单一时钟流逝时间。当多个会话在不同 CPU 核上并行执行,DB CPU 就可能远超单个 DB Time 秒数。
为什么12c更容易看到>100%?
12c 默认启用更多并行特性(如自动并行度 PARALLEL_DEGREE_POLICY=AUTO)、引入 In-Memory Column Store 后的向量化扫描,以及更激进的 PGA 内存管理,都会放大多核 CPU 时间的累积效应。再加上现代服务器普遍 32+ 核,DB CPU 累加后除以 DB Time,结果自然容易突破 100%。
-
DB Time是标量:1 秒就是 1 秒,不随核数变化 -
DB CPU是向量和:48 核上各跑 1 秒,DB CPU就是 48 秒 - AWR 报告里显示的百分比 =
(DB CPU / DB Time) * 100%,所以 48 / 40 = 120% 完全合理 - 如果
DB CPUDB Time,反而说明大量时间花在等待(IO、锁、网络),CPU 利用率偏低
别被 Top 5 Events 里的“CPU”误导
AWR 的 Top 5 Timed Events 里如果出现 CPU 作为第一项,很多人会立刻怀疑 SQL 或代码问题。但这里 CPU 指的是非空闲等待中的 CPU 消耗汇总,并非异常信号——它只是告诉你“数据库确实干了很多活”,而不是“干了错的活”。
真正要警惕的是:
- 同一 SQL 的
cpu_time在v$sql中持续增长,且executions很低 → 可能执行计划劣化 -
v$session里某个 SID 的CPU used by this session值远高于其他会话(比如 10 倍以上)→ 该会话对应 SQL 或 PL/SQL 需查 - AWR 报告中
SQL ordered by CPU Time排名靠前的语句,Elapsed Time却不高 → 多半是短平快但高频执行的小 SQL,未必是瓶颈
什么时候该干预?
单纯 CPU Time > 100% 不需要处理。但若伴随业务延迟上升、load average 持续高于 CPU 核数、或 top 显示 oracle 进程长期占满单核(如 99.9%),才需深入:
- 用
select * from v$active_session_history where session_state = 'ON CPU' and sample_time > sysdate - 1/24找正在吃 CPU 的会话 - 对高 CPU 的 SID,立即查
v$session.sql_id和v$sql_plan,重点看是否有全表扫描、嵌套循环未走索引、或HASH JOIN输入过大 - 确认统计信息是否过期:
dba_tables.last_analyzed超过 7 天,或num_rows与count(*)相差 >20%,就得重收集 - 避免直接杀会话;优先用
alter system kill session '&sid,&serial#' immediate并配合sql_id加绑定变量或改写
最常被忽略的一点:AWR 报告里的 CPU Time 是累计值,它不反映瞬时压力。一个 10 分钟的 AWR 快照里 CPU Time = 1200s,只说明这期间所有 CPU 核总工作了 1200 秒——可能是 12 核各忙 100 秒,也可能是 1 核狂转 1200 秒。得结合 top -H 或 pidstat -t 看线程级分布,才能判断是不是真有单线程卡死。











