ash不记录触发器调用堆栈,因采样仅保留顶层执行上下文,触发器作为pl/sql隐式子单元不展开;sql_id恒为外层dml,current_obj#常为0或负数,program_id在12c+才稳定且仅存于v$sql而非ash。
ash 本身不记录触发器调用堆栈,你查 v$active_session_history 永远看不到 trigger 字样——这不是查询姿势问题,是 oracle 底层设计限制。
为什么 V$ACTIVE_SESSION_HISTORY 查不到触发器堆栈?
Oracle 的 ASH 采样只保留会话在那一秒的“顶层执行上下文”,而触发器属于被 PL/SQL 引擎隐式调用的子单元,其执行帧不会展开到 ASH 行中。你看到的 sql_id 几乎总是外层 DML(比如 UPDATE orders),不是触发器内部的语句。
-
current_obj#常为 0 或负数(尤其访问字典表时),说明当前执行不在用户对象上下文中 -
program_id在 12c+ 才稳定填充,且仅对 V$SQL 有效;ASH 行里没有该字段 - 即使触发器里执行了
SELECT COUNT(*) FROM user_tables,ASH 中也只会显示event = 'latch: row cache objects',不会带出调用来源
怎么间接确认是触发器在捣鬼?盯住这三类行为指纹
别找“触发器名”,找它留下的运行痕迹。以下组合在 ASH 中高频出现,基本可锁定触发器问题:
-
event = 'latch: row cache objects'+p1是 2/6/7/10(对应dc_tables、dc_users等)→ 触发器里查了数据字典 -
sql_id = '00000000000000000000000000000000'+event IN ('library cache lock', 'latch: shared pool')→ 触发器内 SQL 正在硬解析 -
program = 'ora_cjq0_*'或program LIKE '%mmon%'+pga_allocated > 100*1024*1024→ 自治事务频繁提交,后台进程被反复唤醒
如何从 ASH 样本反推触发器逻辑?必须交叉验证
单靠 ASH 不行,得连查三张视图。关键路径是:V$ACTIVE_SESSION_HISTORY → V$SQL → DBA_OBJECTS:
- 先抓可疑样本:
SELECT sql_id, COUNT(*) c FROM v$active_session_history WHERE sample_time > SYSDATE - 1/1440 AND event LIKE 'latch:%' GROUP BY sql_id ORDER BY c DESC FETCH FIRST 3 ROWS ONLY; - 对每个
sql_id查V$SQL:SELECT program_id, program_line#, sql_text FROM v$sql WHERE sql_id = '<xxx>';</xxx>→ 若program_id > 0,说明该 SQL 是由某个存储对象调用的 - 最后定位对象类型:
SELECT object_name, object_type FROM dba_objects WHERE object_id = &program_id;→ 若object_type = 'TRIGGER',坐实
容易被忽略的坑:11g 和 12c 的 program_id 行为不一致
11g 的 V$SQL.program_id 基本不可信,常为 0 或随机值;12c+ 才真正稳定记录触发器 ID。如果环境是 11g,只能靠人工比对:
- 看
sql_text里是否含典型触发器表名(如INSERT INTO audit_log) - 结合命名惯例:比如
sql_text含trg_orders_bru,再查DBA_TRIGGERS确认是否存在同名触发器 - 检查
V$SESSION的plsql_entry字段(若非空):有时能捕获到TRIGGER_NAME片段,但不稳定
真正的调用堆栈只能在 12c+ 的 V$SQL_PLAN 中通过 other_xml 解析获得,ASH 永远只是线索入口,不是终点。











