一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

通过Oracle 19c ASH分析特定模块CPU消耗的方法

时间:2026-06-23 08:54:57 编辑:袖梨 来源:一聚教程网

必须加 session_state = 'ON CPU',因为 MODULE 仅标识应用模块,不区分会话状态;不加该条件会混入等待、空闲等无效样本,导致将“慢模块”误判为“CPU 模块”。

直接查 v$active_session_historymodule 匹配 + session_state = 'on cpu' 的样本数,就能定位模块级 cpu 消耗;但 module 值易被应用覆盖、大小写敏感、且历史数据必须走 dba_hist_active_sess_history,不能只依赖内存视图。

为什么 MODULE 过滤要加 session_state = 'ON CPU'

MODULE 字段只是应用层打标(比如 Spring Boot 设置 setModule),它本身不区分会话状态。同一个模块可能大量时间在等待 I/O 或锁,真正在 CPU 上跑的只是其中一小部分。不加 session_state = 'ON CPU',统计结果会混入大量无效等待样本,把“慢模块”误判成“CPU 模块”。

  • 只过滤 MODULE = 'ORDER-SVC':得到的是该模块所有活跃会话的总采样数,含等待、空闲、解析等全部状态
  • AND session_state = 'ON CPU':才真正反映该模块在 CPU 上实际执行的时间占比
  • 若模块名来自 JDBC 的 setClientInfo,注意 Oracle 默认截断为 48 字节,超长会被截断或丢弃

MODULE 值大小写与空格问题怎么处理

Oracle 对 MODULE 字段做精确匹配,不自动 trim 空格、不忽略大小写。常见坑是应用代码里写了 'payment-gw '(末尾带空格)或 'Payment-GW',而查询时用 = 'payment-gw' 就查不到。

  • 统一用 UPPER(TRIM(module)) = UPPER(TRIM('payment-gw')) 做安全比对
  • 先探查真实值:SELECT DISTINCT TRIM(module) FROM v$active_session_history WHERE sample_time > SYSDATE - 1/1440 AND module IS NOT NULL AND ROWNUM
  • 避免用 LIKE '%payment%' 全模糊——容易跨模块误命中,比如 'PAYMENT-GW''REFUND-PAYMENT' 都会被扫中

查历史模块 CPU 消耗必须用 DBA_HIST_ACTIVE_SESS_HISTORY

v$active_session_history 只保留约 1 小时内存数据,想看昨天下午 3 点的 MODULE = 'INVOICE-BATCH' 的 CPU 情况,必须切到磁盘归档视图。但这里有个硬限制:DBA_HIST_ACTIVE_SESS_HISTORYMODULE 字段只存 AWR 快照时刻的值,不是每秒采样都记,所以精度下降——它只反映快照周期内(默认 60 分钟)该模块是否活跃过,不保证覆盖瞬时尖刺。

  • 必须加时间条件:sample_time BETWEEN TIMESTAMP '2026-06-12 15:00:00' AND TIMESTAMP '2026-06-12 16:00:00',不能用 SYSDATE - 1
  • RAC 环境下该视图已聚合所有实例,无需手动 UNION ALL,但要注意 instance_number 字段可用于下钻单节点
  • 如果发现某模块在历史视图中 MODULE 为空,大概率是应用未设置,或设置了但被 LogMiner、JOB 等后台会话覆盖(后台会话常清空 MODULE)

如何关联 MODULE 和具体 SQL_ID 并排除干扰

一个模块可能跑几十条 SQL,光知道 MODULE = 'USER-PROFILE' 吃了 200 个 CPU 样本,没法定位根因。得把 MODULE、SQL_ID、PLAN_HASH_VALUE 三者绑在一起查,同时排除解析、递归调用等非业务 SQL 干扰。

  • sql_id IS NOT NULL 过滤掉硬解析、PL/SQL 执行等无 SQL_ID 的行
  • 排除系统 SQL:AND sql_id NOT IN (SELECT sql_id FROM v$sql WHERE command_type IN (2, 3, 6))(2=INSERT, 3=SELECT, 6=UPDATE,其余多为递归)
  • 同一 sql_id 可能对应多个执行计划,必须带 sql_plan_hash_value 分组,否则会把低效计划和高效计划混在一起统计
  • 示例片段:SELECT module, sql_id, sql_plan_hash_value, COUNT(*) cpu_samples FROM dba_hist_active_sess_history WHERE module = 'USER-PROFILE' AND session_state = 'ON CPU' AND sample_time BETWEEN ... GROUP BY module, sql_id, sql_plan_hash_value ORDER BY cpu_samples DESC

MODULE 是应用可观测性的入口,但它本身不携带执行上下文。查出高 CPU 模块后,下一步永远要落到 SQL_ID + 执行计划 + 绑定变量组合上——否则你优化的只是表象,不是执行逻辑。

热门栏目