dbms_profiler无法运行的90%原因是权限不足或配套表未创建,需检查包状态、授权execute、执行profload.sql和proftab.sql脚本,并确保start/stop在同session内成对调用且及时commit。
dbms_profiler 跑不起来,90% 是权限或表没建好,不是代码问题。
DBMS_PROFILER.START_PROFILER 报 ORA-06576 或 ORA-06528
这是最常见卡点:包存在但不可调用。根本原因只有两个——权限缺失,或配套表未创建。
-
SELECT * FROM all_objects WHERE object_name = 'DBMS_PROFILER'返回空或状态非VALID,说明包没安装;需 DBA 运行@?/rdbms/admin/profload.sql - 包存在但报
ORA-06576: not a valid procedure or function name,大概率是没授权:GRANT EXECUTE ON DBMS_PROFILER TO your_user(不能靠角色继承) - 即使能 START,
PLSQL_PROFILER_DATA仍为空?检查是否运行过@?/rdbms/admin/proftab.sql——这个脚本建三张核心表和一个序列,普通用户无权执行,必须 DBA 操作
STOP_PROFILER 执行了,但 PLSQL_PROFILER_DATA 查不到数据
Profiler 数据默认缓存在 session 级别,不显式刷出就看不见。这不是 bug,是设计行为。
- 必须成对调用:
DBMS_PROFILER.START_PROFILER→ 执行目标 PL/SQL →DBMS_PROFILER.STOP_PROFILER -
STOP_PROFILER后立刻COMMIT,否则数据滞留在事务缓存中,查PLSQL_PROFILER_DATA为空 - 不要依赖会话断开自动 flush;
DBMS_PROFILER.FLUSH_DATA可手动刷,但仅限当前 session,且不保证跨 session 可见 -
run_comment参数别传空字符串,否则PLSQL_PROFILER_RUNS里全是NULL,后续定位困难;建议用'unit_x_' || SYSDATE
覆盖率报告显示某行“未覆盖”,但逻辑上肯定执行了
行号映射错乱不是 profiler 坏了,而是它绑定的是数据库里编译后的单元,不是你本地编辑器里的文件。
- 先查真实源码:
SELECT text FROM USER_SOURCE WHERE name = 'YOUR_PROC_NAME' AND type = 'PROCEDURE',比对行号是否一致 -
PLSQL_PROFILER_UNITS.UNIT_TYPE必须严格匹配,比如 PACKAGE BODY 不能写成 PACKAGE - 动态 SQL(
EXECUTE IMMEDIATE)里的 PL/SQL 片段完全不会被采集,这部分永远显示 0% - 短路逻辑(如
IF flag AND expensive_func() THEN ...)中expensive_func()行可能标为“未执行”,这是控制流跳过,不是漏测
PLSQL_PROFILER_DATA 查询慢,COUNT(*) 都卡住
这张表没有主键、无索引,多人共用 schema 时极易膨胀到百万级。直接全表扫等于拖库。
- 永远带过滤条件:
WHERE runid = :rid AND unit_number = :un,别查全量 - 关联
PLSQL_PROFILER_UNITS时用unit_owner和unit_name先缩小范围,再连ALL_SOURCE - 避免在生产环境反复不清表;测试前用
DELETE FROM plsql_profiler_data WHERE runid IN (SELECT runid FROM plsql_profiler_runs WHERE run_comment LIKE '%test%')清理指定批次 - 导出 HTML 报告时,先聚合再渲染:用
GROUP BY line#统计TOTAL_OCCUR,而不是逐行 JOIN
最容易被忽略的是:每次 START/STOP 必须在同一个数据库 session 内完成。跨 session、跨连接、甚至某些 ORM 自动 commit 后的隐式断连,都会让 profiler 数据丢失。别信“我刚才明明 stop 了”,先看 session ID 是否一致。











