module和action需应用显式设置,否则为空或默认客户端名;查ash时用=精确匹配、in替代or,结合sql_id/event/session_state定位真实瓶颈。
直接查 module 和 action 是可行的,但必须确认它们真被应用设置了——oracle 不会自动填充这两个字段,没设就永远查不到。
为什么 MODULE 字段经常为空或全是 'SQL*Plus'?
Oracle 的 MODULE 和 ACTION 完全依赖应用层调用 DBMS_APPLICATION_INFO.SET_MODULE 或 JDBC 的 setClientInfo("ApplicationName", "Action") 才会写入。未显式设置时,V$SESSION 和 ASH 里默认填的是客户端程序名(如 sqlplus.exe、oracle@host),不是业务模块名。
- 检查当前会话是否已设:运行
SELECT module, action FROM v$session WHERE sid = SYS_CONTEXT('USERENV', 'SID'); - JDBC 应用需在连接后立即调用
conn.setClientInfo("OrderService", "createOrder"),不能只靠连接串参数 - PL/SQL 包内调用前必须先
DBMS_APPLICATION_INFO.SET_MODULE('Payment', 'processRefund'),且建议在异常处理块中加SET_MODULE(NULL, NULL)清理
在 V$ACTIVE_SESSION_HISTORY 中正确过滤 MODULE 的写法
ASH 的 MODULE 字段和 V$SESSION 同源,但采样有延迟——某会话刚设完 MODULE,下一秒采样才可能捕获。所以查不到不等于没设,可能是时间窗口太窄或采样错过。
- 查最近 5 分钟内某模块的活跃样本:
SELECT sql_id, event, session_state, pga_allocated FROM v$active_session_history WHERE module = 'Inventory' AND sample_time > SYSDATE - 1/288 ORDER BY sample_time DESC; - 避免用
LIKE '%Inv%'——MODULE是固定长度 VARCHAR2(48),尾部空格会被保留,=比LIKE更准也更快 - 若想合并多个模块(如 'Order' 和 'Payment'),用
IN ('Order', 'Payment'),别用OR module = 'Order' OR module = 'Payment',后者可能让执行计划走全表扫描
ACTION 字段的典型误用和排查价值
ACTION 比 MODULE 更细粒度,常用于标记具体操作(如 'loadCustomerData'、'rebuildIndex')。但它在 ASH 中的稳定性差于 MODULE:很多应用只设一次 MODULE,却在不同逻辑分支反复覆盖 ACTION,导致单次采样值不可靠。
- 高频变更的
ACTION更适合配合sample_time做趋势分析,例如:SELECT action, COUNT(*) c FROM v$active_session_history WHERE module = 'ReportEngine' AND sample_time BETWEEN SYSDATE-1/24 AND SYSDATE GROUP BY action ORDER BY c DESC; - 若发现
ACTION值为 'UNKNOWN' 或 'NULL',优先检查应用日志中是否抛出ORA-06502(字符超长)——ACTION最大长度仅 32 字节,中文占 3 字节/字,超长会被截断或置空 - 不要依赖
ACTION做唯一标识:同一业务逻辑可能因异常路径进入不同ACTION,但真实性能瓶颈在共用的 SQL 上
MODULE + ACTION 联合分析的真实瓶颈点
单独看 MODULE 只能定位到服务层,加上 ACTION 才可能下沉到功能点。但真正关键的是把它们和等待事件、执行状态交叉——比如同是 MODULE = 'Billing',ACTION = 'generateInvoice' 样本全为 ON CPU,而 ACTION = 'sendEmail' 样本全是 SQL*Net message to client,说明前者是计算瓶颈,后者是网络或下游依赖问题。
- 查某模块下最耗 CPU 的子操作:
SELECT module, action, COUNT(*) cpu_ms FROM v$active_session_history WHERE module = 'Shipping' AND session_state = 'ON CPU' AND sample_time > SYSDATE - 1/720 GROUP BY module, action ORDER BY cpu_ms DESC; - 注意
sample_time精度是微秒级,但采样间隔约 1 秒,所以COUNT(*)× 10 ≈ 实际毫秒级 CPU 消耗,不是精确值 - 如果联合查询返回空,先确认该模块是否真在跑——
SELECT COUNT(*) FROM v$session WHERE module = 'Shipping';,再查V$SESSION_CONNECT_INFO确认客户端协议是否支持传递MODULE(旧版 ODP.NET 有时会丢弃)
MODULE 和 ACTION 不是 Oracle 自动打的标签,是应用自己贴的“病历号”。没贴好,再强的 ASH 也读不出病因;贴得太细(比如每行代码都设 ACTION),反而让分析失焦。真正该盯住的,永远是 sql_id + event + session_state 这三列组合。











