AWR报告生成失败主因是快照不存在或权限不足;CPU time占比高未必异常,需结合DB Time/Elapsed比值及绝对值分析;物理读高不等于缺索引,应查Buffer Hit Ratio和执行计划变化;SQL未共享常因大小写、绑定变量类型等导致游标无法复用。
AWR报告生成失败:快照ID不存在或权限不足
直接报 error: 指定的开始快照id不存在 或 ora-06532: 下标超出限制,说明你没拿到有效数据源。这不是脚本问题,是前置条件没满足。
常见错误现象:运行 @?/rdbms/admin/awrrpt.sql 后卡在快照选择环节,或报错退出;用非 SYSDBA 账户登录时直接拒绝访问视图。
- 先确认快照是否存在:
SELECT snap_id, begin_interval_time FROM dba_hist_snapshot ORDER BY snap_id DESC;—— 如果返回空,说明 AWR 未采集(可能被禁用、SYSAUX 表空间满、或数据库刚启动还没到首次快照时间) - 手动触发一次快照:
EXEC dbms_workload_repository.create_snapshot();,再查一遍 - 必须用
sqlplus / as sysdba连接;SELECT权限不够,dba_hist_*视图需要SELECT_CATALOG_ROLE或直接SYSDBA - RAC 环境下别用
awrrpt.sql查全局问题,改用awrgrpt.sql,否则只看到单实例数据
Top 5 Timed Events 里 “CPU time” 高但数据库不慢?
“CPU time” 排第一不等于真有性能问题——它只是说“当前时间段内,活跃会话花在 CPU 上的时间占比最高”,但这个“高”可能是健康的。
使用场景:系统负载正常上升(比如业务高峰),CPU time 占比从 40% 升到 75%,但响应时间稳定、无用户投诉,那大概率是合理压测。
容易踩的坑:只看百分比,忽略绝对值和并发上下文。
- 查
DB Time和Elapsed的比值:如果DB Time / Elapsed接近 1,说明数据库大部分时间都在干活,不是空等;如果远大于 1(比如 8.5),说明高并发下资源争抢已明显 - 对比“问题时段”和“正常时段”的
CPU time绝对值(单位:秒),而不是只盯百分比。增长 3 倍 + 响应延迟翻倍,才值得深挖 - 接着看
SQL ordered by CPU Time模块,定位具体哪几条 SQL 吃掉了 CPU,别在事件层打转
Physical Reads 高就一定缺索引?
不一定。物理读多,只说明数据没在 buffer cache 里,但原因可能是缓存淘汰、大表扫描、还是归档日志刷盘,得结合上下文判断。
参数差异:同一 SQL,在不同负载下 Physical Reads 可能差一个数量级——比如夜间维护任务清空 buffer cache 后首次执行,必然全物理读。
性能影响:盲目加索引可能让 DML 变慢、占用更多 SGA,甚至引发 latch contention。
- 先看
Buffer Hit Ratio:如果整体命中率 >95%,单条 SQL 物理读高,更可能是该 SQL 访问了冷数据,而非设计缺陷 - 查
Tablespace IO Stats部分:如果集中在USERS表空间,而其他表空间 IO 平稳,才指向具体对象问题 - 用
dba_hist_sqlstat关联历史执行计划:SELECT plan_hash_value, executions, disk_reads FROM dba_hist_sqlstat WHERE sql_id = 'xxx' ORDER BY snap_id;—— 看是不是某次升级后执行计划突变导致全表扫描
ADDM 建议说“SQL 语句未共享”,但 V$SQL 里 child_number 是 1
这是典型误读。ADDM 提到的“未共享”不是指硬解析,而是指 SQL 文本虽相同,但因绑定变量类型、优化器环境(如 optimizer_mode)、或对象统计信息版本不同,导致无法复用同一个 cursor。
真实原因常被忽略:应用拼接 SQL 时多了一个空格、大小写混用、或用了同义词但定义者权限不同。
可给出简短示例:
SELECT /*+ FULL(t) */ * FROM employees t WHERE dept_id = :1; SELECT /*+ FULL(t) */ * FROM EMPLOYEES t WHERE dept_id = :1;
这两条在 Oracle 看来就是两条不同 SQL(EMPLOYEES vs employees),哪怕表实际是同一个。
- 查
v$sql_shared_cursor:对问题sql_id执行SELECT * FROM v$sql_shared_cursor WHERE sql_id = 'xxx';,看哪一列是Y(比如OPTIMIZER_MISMATCH、TRANSLATION_MISMATCH) - 用
DBMS_SQLTUNE.REPORT_SQL_MONITOR看实时执行时的绑定变量实际类型,确认是否和预编译时不一致 - 检查应用层是否启用了
cursor_sharing = FORCE,这反而会制造更多子游标
AWR 不是万能诊断仪,它只记录发生了什么;真正难的是把 db file sequential read 和应用里的一个订单查询逻辑、把 library cache lock 和某个凌晨跑的统计 job 关联起来——这种映射没有自动工具能做,得靠你对业务和系统的双重理解。



















