dbms_profiler跑不起来的根本原因是权限不足或未初始化:需dba授权execute、运行profload.sql建表,并确保start/stop_profiler与commit成对执行;行号不准源于源码与编译单元不一致。
dbms_profiler 为什么跑不起来,连 start_profiler 都报错?
根本原因通常是权限或初始化没做对。不是代码写错了,而是当前用户根本没被授权调用这个包,或者数据库没启用 profiler 功能。
- 检查是否已安装:用
SELECT * FROM all_objects WHERE object_name = 'DBMS_PROFILER'确认包存在且状态为VALID - 必须由 DBA 授予
EXECUTE权限:GRANT EXECUTE ON DBMS_PROFILER TO your_user,不能只靠角色继承 - 需要建配套表:运行
@?/rdbms/admin/profload.sql(服务端路径),普通用户无权执行,得让 DBA 跑一次 - 常见错误
ORA-06576: not a valid procedure or function name就是包没装好或权限缺失
profiler 数据插进去了,但 PLSQL_PROFILER_DATA 里全是空的?
不是没采集,是没“停”——STOP_PROFILER 没调,或者调了但事务没提交,数据还卡在 session 缓存里。
- 必须显式调用
DBMS_PROFILER.STOP_PROFILER,不能依赖会话断开自动刷出 - 调完
STOP_PROFILER后,立刻执行COMMIT,否则PLSQL_PROFILER_DATA查不到新记录 - 如果跑的是匿名块或存储过程,确保 profiler 在目标代码执行前已
START,且同一 session 内完成启停 - 注意
run_comment参数别为空,否则后续查PLSQL_PROFILER_RUNS时难定位,建议用SYSDATE || '_my_proc'这类可识别值
覆盖率数字不准:UNIT_OWNER 对不上,LINE# 跳变,甚至显示 0% 执行行
核心问题是 profiler 绑定的是「编译后的单元」,不是你编辑器里正在看的源码文件。源码改过、重编译过、用了同义词或远程对象,都会导致行号映射错乱。
- 务必用
SELECT * FROM USER_SOURCE WHERE NAME = 'YOUR_PROC_NAME'核对当前实际存储的代码,别信本地文件 -
PLSQL_PROFILER_UNITS.UNIT_TYPE是PROCEDURE还是PACKAGE BODY得看真实定义,类型不对会导致UNIT_NUMBER关联失败 - 动态 SQL(
EXECUTE IMMEDIATE)里的 PL/SQL 片段不会被 profiler 覆盖,这部分永远算“未执行” - 条件分支里短路逻辑(比如
AND左边为 false 就不走右边)会导致某些行看似“未覆盖”,其实是控制流天然跳过,不是 bug
想导出覆盖率报告,但 plsql_profiler_data 太大,COUNT(*) 都卡住
直接查全量表等于扫全库 profiler 历史,尤其多人共用一个 schema 时,PLSQL_PROFILER_DATA 可能有百万级行。得先过滤再聚合。
- 永远带上
runid条件:先从PLSQL_PROFILER_RUNS查出你要分析的RUNID,再关联其他表 - 避免
SELECT *,只取关键字段:UNIT_NUMBER,LINE#,TOTAL_OCCURRENCES,用GROUP BY聚合后判断是否 > 0 - 临时表提速:把某次 run 的相关 unit 和 data 插入全局临时表,再 join,比反复子查询快得多
- 注意
TOTAL_OCCURRENCES是累计值,不是布尔开关;0 表示真没执行,NULL 表示该行未被 profiler 识别(比如注释行、空行)
真正麻烦的从来不是怎么启动 profiler,而是怎么确认你看到的行号、单元名、执行次数,确实对应你此刻想调优的那一段代码。中间差一次重编译、一个未提交、一个大小写拼写,结果就完全对不上。










