AWR在多租户环境下默认只采集CDB$ROOT级数据,PDB真实负载被淹没;必须切换容器或用CON_ID过滤DBA_HIST_*视图才能分析单个PDB的SQL、等待事件及性能指标。

AWR 在多租户环境下不能直接按传统方式用——它默认只采集 CDB$ROOT 级别的聚合数据,PDB 的真实负载会被淹没。必须显式切换到目标 PDB 上下文,或使用 DBA_HIST_* 视图加 CON_ID 过滤,否则看到的“高负载”可能全是其他 PDB 拉的平均值。
为什么 AW R 报告里看不到某个 PDB 的 SQL?
AWR 快照默认只在 CDB$ROOT 中生成,所有 PDB 的活动都汇总进 CDB 级统计。你查 DBA_HIST_SQLSTAT 或跑 @?/rdbms/admin/awrrpt.sql 时,若没指定容器上下文,就只会看到 CDB 总体视图,根本看不到单个 PDB 的慢 SQL。
- 确认当前连接的是 CDB$ROOT:
SHOW CON_NAME输出应为CDB$ROOT - 想分析某 PDB(如
ORCLPDB),先切过去:ALTER SESSION SET CONTAINER = ORCLPDB; - 再查历史 SQL:
SELECT sql_id, elapsed_time_delta FROM DBA_HIST_SQLSTAT WHERE snap_id BETWEEN 100 AND 110 ORDER BY elapsed_time_delta DESC; - 注意:
DBA_HIST_*视图中都有CON_ID字段,跨容器查询时必须加WHERE CON_ID = <pdb_con_id>,不能只靠INST_ID
如何生成特定 PDB 的 AWR 报告?
Oracle 官方脚本 @?/rdbms/admin/awrrpt.sql 不支持直接选 PDB —— 它只认实例和数据库名。要得到某 PDB 的报告,得手动构造查询,或用 awrrpti.sql(交互式)并配合 CON_ID 参数。
- 先查目标 PDB 的
CON_ID:SELECT CON_ID, NAME FROM V$PDBS WHERE NAME = 'ORCLPDB'; - 用
awrrpti.sql(不是awrrpt.sql):它会提示输入dbid、inst_num和num_days,最后一步会问Enter value for con_id:,填上查到的CON_ID - 若用 PL/SQL 批量导出,必须调用
DBMS_WORKLOAD_REPOSITORY.AWR_REPORT_HTML并传入con_id参数,否则返回空或 CDB 总览 - 别指望
GV$视图能自动跨 PDB 聚合——GV$ACTIVE_SESSION_HISTORY里每行带CON_ID,但GV$SQL不带,查 PDB 级 SQL 必须用V$SQL+ 切容器
PDB 级等待事件容易被 CDB 层掩盖
比如某个 PDB 因大量 enq: TX - row lock contention 卡住,但在 CDB 级 AWR 的 Top Events 里可能排不进前五,因为其他 PDB 正在做大量物理读,把等待时间摊薄了。
- 看等待事件必须进 PDB 上下文:
ALTER SESSION SET CONTAINER = ORCLPDB;后再查DBA_HIST_SYSTEM_EVENT -
EVENT字段值一样,但CON_ID不同,意味着同一事件在不同 PDB 中独立发生,不能合并统计 - 特别注意
log file sync:如果多个 PDB 共享同一个在线日志组,这个事件会出现在 CDB 级,但实际瓶颈可能只来自其中一个 PDB 的频繁提交 - RAC 环境下更麻烦:
GV$视图需配合CON_ID+INST_ID双重过滤,否则一个节点上的 PDB 等待会被误认为是另一个节点的问题
最常被忽略的一点:AWR 默认不采集 PDB 级的 Buffer Cache 命中率、Library Cache Reloads 这类指标——它们只存在于 CDB$ROOT 的 V$ 视图中。真要诊断 PDB 内部内存压力,得靠实时的 V$PDB_STATS(12.2+)或在 PDB 内执行 SELECT * FROM V$LIBRARYCACHE;,而不是翻 AWR 报告。


















