ASH 不显示触发器名,因其仅记录外层DML的sql_id和状态,触发器作为PL/SQL递归调用不展开堆栈,导致PLSQL_ENTRY_OBJECT_ID为空;需通过空sql_id、高频row cache latch争抢、ON CPU+PL/SQL EXECUTE等行为指纹交叉验证,并结合V$SQL.program_id反查dba_objects确认触发器。
ash 本身不显示触发器名,但能暴露它留下的行为指纹——高频递归调用、硬解析、row cache latch争抢或隐式锁等待才是关键线索。
为什么 V$ACTIVE_SESSION_HISTORY 查不到触发器名
触发器执行属于 PL/SQL 递归调用,ASH 只记录采样瞬间的外层 SQL 状态,sql_id 是 INSERT/UPDATE 那条 DML,不是触发器内部语句。堆栈未展开,所以 PLSQL_ENTRY_OBJECT_ID 和 PLSQL_ENTRY_SUBPROGRAM_ID 在 ASH 中为空或为 0,无法直接关联到触发器对象。
-
sql_id常为空('00000000000000000000000000000000')或指向父 DML,但program_id字段在 12c+ 才稳定填充 -
current_obj#多为 0 或负数,尤其当触发器查字典表(如SELECT COUNT(*) FROM user_tables)时,会高频触发row cache objects等待 - 若触发器含
PRAGMA AUTONOMOUS_TRANSACTION,ASH 中会出现大量短生命周期的ON CPU+log file sync组合样本
怎么从 sql_id 关联到触发器逻辑
不能只查 ASH,必须交叉验证三步:先抓可疑 sql_id,再查 V$SQL.program_id,最后反推对象类型。
- 提取高频空
sql_id样本:SELECT sql_id, COUNT(*) FROM v$active_session_history WHERE sample_time > SYSDATE - 1/1440 AND sql_id IN ('00000000000000000000000000000000', NULL) GROUP BY sql_id ORDER BY 2 DESC FETCH FIRST 5 ROWS ONLY - 对每个
sql_id查V$SQL:SELECT program_id, program_line#, sql_text FROM v$sql WHERE sql_id = 'xxx';若program_id > 0,说明来自存储对象 - 反查对象:
SELECT object_name, object_type FROM dba_objects WHERE object_id = &program_id;object_type = 'TRIGGER'即坐实 - 11g 不支持
program_id稳定记录,只能靠sql_text中表名 + 触发器命名惯例(如trg_t1_bri)人工比对
识别触发器引发的典型 ASH 模式
以下组合同时出现,基本可判定是触发器问题,而非普通 SQL 性能差:
-
sql_id为空 +event为latch: shared pool或library cache lock→ 触发器内动态 SQL 导致硬解析 -
session_state = 'ON CPU'+sql_opname = 'PL/SQL EXECUTE'+program含oraagent或oracle@→ PL/SQL 层执行密集,非 SQL 引擎瓶颈 -
event = 'row cache objects'+current_obj# <= 0+machine字段集中于同一应用服务器 → 触发器频繁访问数据字典 -
blocking_session为空但final_blocking_session有值,且sql_id为空 → 触发器中隐式更新无索引表,引发 TX 锁升级和级联阻塞
别忽略 PLSQL_ENTRY_OBJECT_ID 在 19c 的新用途
Oracle 19c 对 V$ACTIVE_SESSION_HISTORY 增强了 PL/SQL 调用上下文支持,部分场景下 PLSQL_ENTRY_OBJECT_ID 已能非空。但它仍不稳定,仅在触发器被显式调用(如通过 EXECUTE IMMEDIATE 调用另一触发器)或开启 PLSQL_DEBUG 时才可能填充。
- 不要依赖它做主判断依据,但可作为辅助线索:
SELECT DISTINCT plsql_entry_object_id FROM v$active_session_history WHERE sample_time > SYSDATE - 1/1440 AND plsql_entry_object_id > 0 - 查出 ID 后,必须立刻查
dba_objects确认类型,避免误判为函数或过程 - 即使填了,也需结合
time_waited和event判断是否真由该触发器主导耗时——因为 PL/SQL 执行路径可能嵌套多层
最易被忽略的是:触发器性能问题往往不表现为单条 SQL 慢,而是让原本毫秒级的 DML 变成秒级,且 ASH 中看不到对应 sql_id。盯住“空 sql_id + 高频等待 + ON CPU 累积”这个三角组合,比找名字更可靠。



















