直接查v$active_session_history可能看不到pdb信息,因为ash默认按实例维度采样,不自动关联当前容器上下文;必须先在目标pdb内执行alter session set container = pdb_name,才能使pdb_name字段显示真实值。

为什么直接查V$ACTIVE_SESSION_HISTORY可能看不到PDB信息
ASH 默认只记录 CDB$ROOT 视图级别的会话状态,V$ACTIVE_SESSION_HISTORY 中的 PDB_NAME 列在未显式切换容器时为空或为 CDB$ROOT,哪怕你连接的是某个 PDB。这不是权限问题,而是视图绑定机制导致的——Oracle 19c 的 ASH 内存采样按实例维度组织,不自动关联当前容器上下文。
必须先在目标 PDB 内执行查询,才能让 PDB_NAME 字段填充真实值:
- 用
sqlplus / as sysdba连接后,立刻运行ALTER SESSION SET CONTAINER = pdb01;(替换成你的 PDB 名) - 再查
V$ACTIVE_SESSION_HISTORY,PDB_NAME才会显示pdb01 - 不能靠
SELECT SYS_CONTEXT('userenv', 'con_name') FROM dual判断是否已生效——它返回当前 session 的 container,但 ASH 采样是后台 MMNL 进程做的,它不继承你的 session context
如何快速定位PDB级IO热点SQL
AWR 报告里的 “Top Segments by Physical Reads” 只能告诉你哪张表读得多,但无法区分是哪个 PDB 在读。ASH 是唯一能交叉 PDB_NAME、SQL_ID 和 EVENT 的实时源。
执行这个查询(在目标 PDB 内):
SELECT sql_id, COUNT(*) cnt, MAX(event) event, MAX(pdb_name) pdb_name
FROM v$active_session_history
WHERE sample_time > SYSDATE - 1/1440
AND event IN ('db file sequential read', 'direct path read', 'cell single block physical read')
GROUP BY sql_id
ORDER BY cnt DESC
FETCH FIRST 5 ROWS ONLY;
注意三点:
- 结果中
pdb_name必须是你刚SET CONTAINER的那个,否则说明没切对 - 如果
event是cell single block physical read,说明 IO 穿透到了 Exadata 存储层,不是数据库缓存问题 - 若同一
sql_id在多个pdb_name下都高频出现,说明该 SQL 被多个 PDB 共享调用(比如 CDB 级公共包),需检查其访问对象是否跨 PDB
为什么PDB间等待事件会互相掩盖
RAC + 多租户环境下,一个 PDB 的 enq: TX - row lock contention 可能被另一个 PDB 的大量 log file sync 平均掉,导致 AWR 报告里 “Top 5 Timed Events” 看不出异常。ASH 按秒采样,能暴露这种时间错位。
关键操作是分 PDB 聚合分析:
- 不要用
SELECT event, COUNT(*) FROM v$active_session_history GROUP BY event—— 这会混掉所有 PDB - 必须加
PDB_NAME分组:SELECT pdb_name, event, COUNT(*) FROM v$active_session_history WHERE sample_time > SYSDATE - 1/24 GROUP BY pdb_name, event ORDER BY COUNT(*) DESC - 特别关注
gc buffer busy acquire或enq: TX类事件在单个 PDB 内占比突增(如从 0.1% → 8%),这比全局 Top 5 更早暴露 RAC 热点块争用 - 如果某 PDB 的
ON CPU样本占比突然升高,且sql_opname = 'PL/SQL EXECUTE',大概率是该 PDB 内触发器或存储过程逻辑变重,不是 SQL 本身慢
ASH和AWR报告的时间窗口必须严格对齐
AWR 报告默认按快照(每小时一次)汇总,而 ASH 是每秒采样。如果你用 AWR 报告里 “14:00–15:00” 这个区间去查 ASH,却用 sample_time BETWEEN TIMESTAMP '2026-07-20 14:00:00' AND TIMESTAMP '2026-07-20 15:00:00',会漏掉边界误差——因为快照实际覆盖的是 begin_snap 到 end_snap 的精确时间点,可能差几十秒。
正确做法是反向从 AWR 报告里抄出快照时间:
- 打开 AWR 报告,在 “Report Summary” 部分找到 “Snap Id” 对应的 “Begin Snap Time” 和 “End Snap Time”
- 用这两个时间戳作为 ASH 查询条件,例如:
sample_time BETWEEN TO_TIMESTAMP('2026-07-20 13:58:12', 'YYYY-MM-DD HH24:MI:SS') AND TO_TIMESTAMP('2026-07-20 14:58:12', 'YYYY-MM-DD HH24:MI:SS') - 别依赖 AWR 报告标题写的“14:00–15:00”,那是四舍五入后的展示值,不是真实采集边界
最易被忽略的是:PDB 级 ASH 数据只存在于该 PDB 的快照中,CDB 级 AWR 报告不会包含 PDB 的 ASH 细节——想看 PDB 级问题,必须在对应 PDB 容器内生成 AWR 报告,再点报告里的 “See ASH data for top sessions” 链接,否则看到的全是 CDB$ROOT 的后台活动。











