CPU 过高
服务器 CPU 已占满。先确认确实是数据库在消耗 CPU,然后沿各分支找到根本原因:执行计划糟糕的查询、执行计划回归、并发过高,或非数据库进程。
真的是数据库在消耗 CPU 吗?
在操作系统侧检查是哪个进程在消耗 CPU。大部分负载是在数据库进程中,还是在相邻进程中(备份、杀毒软件、其他应用)?据此将排查分为两路。
-- OS side: top -o %CPU (or: top -c)
-- DB-side verification:
SELECT ROUND(value,1) AS host_cpu_util_pct FROM v$sysmetric WHERE metric_name='Host CPU Utilization (%)' AND rownum=1;- 是的,是数据库进程在消耗 CPU
- 不是,是相邻进程/备份作业在消耗
负载是如何出现的?
若是数据库在消耗 CPU,识别其模式:是少数几个重型查询占主导、问题在某次变更后突然出现,还是存在高并发/连接争用?
- 少数几个重型查询在大量消耗 CPU
- 突然出现;最近有部署/参数变更
- 大量连接/并发争用
找出消耗 CPU 最多的查询
按 CPU 总消耗取出排名靠前的查询。然后判断每个查询是单次调用开销大(执行计划糟糕),还是单次开销小但调用非常频繁。
SELECT sql_id, executions, ROUND(cpu_time/1e6,1) AS cpu_sec, ROUND(cpu_time/GREATEST(executions,1)/1000,2) AS cpu_ms_per_exec, sql_text
FROM v$sql ORDER BY cpu_time DESC FETCH FIRST 10 ROWS ONLY;- 单次调用开销大;执行计划糟糕/全表扫描
- 单次调用开销小但调用非常频繁
根本原因:执行计划糟糕的查询在大量消耗 CPU
少数几个查询由于全表扫描或糟糕的连接顺序,每次调用都消耗过多 CPU。修正其执行计划是核心解决办法。
根本原因:调用频率过高
这些查询单个开销很小,但每秒被调用数千次;总的 CPU 开销就来源于此。通常是 N+1 模式或未缓存的热点路径。
根本原因:执行计划回归/统计信息过时
系统昨天还正常;在某次部署、参数变更或数据加载后 CPU 飙升。优化器可能切换到了更差的执行计划。
根本原因:高并发/连接争用
单个查询都可以接受,但同时运行的会话太多;活动会话数超过 CPU 核心数会引起上下文切换和 latch/spin 争用。
根本原因:非数据库进程在消耗 CPU
消耗 CPU 的不是数据库,而是相邻进程:同一台机器上的备份/压缩作业、杀毒扫描、日志传送程序或其他应用。