4. AWR与ASH报告深度解读

AWR(Automatic Workload Repository)与ASH(Active Session History)是Oracle性能诊断的两大基石。AWR以小时或更长的快照间隔记录系统级累计统计,回答“这一小时数据库整体在忙什么”;ASH以秒级采样记录活动会话的瞬时状态,回答“某一刻谁在等、等什么”。二者结合,才能把“平均指标正常但用户报慢”的疑难故障定位到具体SQL、具体事件和具体时间点。

一、AWR报告的三层阅读顺序

面对一份几十页的AWR报告,不要从第一页顺序读。推荐按“负载概览 → 时间模型 → Top事件与Top SQL”三层递进。

第一层:负载概览(Load Profile)。关注DB Time、DB CPU、Redo Size、Logical Reads、Physical Reads、Executes、Transactions等每秒值。DB Time是核心:它等于所有前台会话消耗的总时间,若DB Time远大于Elapsed Time乘以CPU核数,说明存在明显排队。例如Elapsed为3600秒、8核,则理论并行上限约28800秒CPU时间;若DB Time达到72000秒,说明平均有约20个会话在并发等待。

第二层:时间模型(Time Model Statistics)。这是AWR中最容易被忽略却最有价值的部分。它把DB Time拆解为DB CPU、sql execute elapsed time、parse time elapsed、connection management call elapsed、sequence load elapsed、hard parse elapsed等。判断性能拐点的关键,是看DB CPU占DB Time的比例:若DB CPU占比超过80%,瓶颈多在CPU计算;若DB CPU占比低而DB Time高,说明大量时间花在等待上,需转向Top Events。

第三层:Top 10 Foreground Events与SQL Statistics。前者按等待时间排序,直接指出“等什么”;后者按Elapsed Time、CPU Time、Buffer Gets、Disk Reads、Executions排序,指出“谁在消耗”。两者必须交叉验证:如果Top Event是db file sequential read,而Top SQL的Buffer Gets极高但Disk Reads不高,则瓶颈可能不在该SQL,而在其他对象的物理读。

二、ASH报告的采样视角

ASH每秒采样一次活动会话,记录session_id、session_serial#、user_id、sql_id、event、wait_class、p1/p2/p3、sample_time等。它的价值在于“时间切片”:可以按分钟聚合,观察某类等待在何时突然上升。

典型用法是查询v$active_session_history或生成ASH报告后查看“Top Events”与“Top SQL”的分钟级分布。例如某系统每天10:00—10:15出现大量enq: TX - row lock contention,而AWR一小时平均值只显示轻微等待。此时ASH能精确定位到具体阻塞会话和SQL_ID。

-- 按分钟统计等待事件分布(示例)
SELECT TO_CHAR(sample_time,'HH24:MI') AS minute,
       event,
       COUNT(*) AS samples
FROM   v$active_session_history
WHERE  sample_time >= SYSDATE - 1/24
GROUP  BY TO_CHAR(sample_time,'HH24:MI'), event
ORDER  BY minute, samples DESC;

该查询输出的是示例结构,实际采样数取决于活动会话数量。若某分钟db file scattered read样本数骤增,而相邻分钟正常,即可判定为性能拐点。

三、时间模型与性能拐点的结合分析

性能拐点通常表现为:某指标在时间轴上出现非线性突变。识别方法有三步:

  1. 定位拐点时刻。用ASH按分钟聚合DB Time或某等待事件,找出突变点。
  2. 确认拐点性质。回到AWR对应快照区间,看DB CPU与等待时间的比例是否改变。若DB CPU不变而某等待事件暴增,说明是外部资源或锁竞争;若DB CPU同步上升,说明是计算量增加。
  3. 关联SQL与对象。用ASH的sql_id关联AWR的SQL Statistics,确认是新增SQL、执行计划变化,还是绑定变量窥探导致计划翻转。
判断拐点时,优先看ASH的分钟级采样,再用AWR的快照区间做定量确认。ASH负责“什么时候”,AWR负责“整体多少”。

四、Top SQL与Top Event的交叉定位

Top SQL不能只看Elapsed Time。一个执行一次但耗时10秒的SQL,与执行十万次但每次0.1毫秒的SQL,优化策略完全不同。建议同时看四个维度:Elapsed Time per Exec、CPU Time per Exec、Buffer Gets per Exec、Disk Reads per Exec。

SQL_IDElapsed(s)ExecutionsElapsed/Exec(ms)Buffer Gets/Exec主要等待
a1b2c3d4360013,600,000850,000db file scattered read
e5f6g7h824002,400,0001.012CPU
i9j0k1l21800180,00010.045enq: TX - row lock

表中数据为教学示例。第一行是典型的大查询,应优化访问路径或增加并行;第二行是高频小SQL,应关注解析与逻辑读;第三行是锁竞争,应检查事务边界与提交频率。

五、实操:从ASH定位阻塞链

当Top Event为enq: TX - row lock contention时,ASH可直接给出阻塞关系。查询v$active_session_history中blocking_session字段,即可还原阻塞树。若阻塞会话本身也在等待,则形成阻塞链,需逐层向上找到根会话。

-- 示例:查找阻塞链
SELECT sample_time, session_id, blocking_session,
       event, sql_id, wait_class
FROM   v$active_session_history
WHERE  blocking_session IS NOT NULL
  AND  sample_time > SYSDATE - 30/1440
ORDER  BY sample_time;

输出中若出现session 120阻塞135、135阻塞140,则根因在120。再查120的sql_id与执行状态,即可判断是未提交事务、批量更新还是应用逻辑缺陷。

AWR + ASH 联合诊断路径 从整体负载到分钟级拐点,再到阻塞根因 AWR 快照层 • Load Profile:DB Time / DB CPU • Time Model:CPU 占比拆解 • Top Events:等待时间排序 • SQL Statistics:Elapsed / Gets 粒度:小时级累计 ASH 采样层 • 每秒活动会话采样 • event / wait_class / sql_id • blocking_session 阻塞链 • sample_time 分钟级聚合 粒度:秒级瞬时 诊断输出 • 性能拐点时刻 • Top SQL 与等待事件 • 阻塞根会话 • 优化方向判断 粒度:可执行结论 时间轴:性能拐点识别 09:00 10:00 10:12 拐点 11:00 正常 轻微等待 row lock 暴增 恢复 阻塞链还原(ASH blocking_session) SID 120 根会话 SID 135 等待 SID 140 等待 → 根因在 SID 120:未提交事务 / 批量更新

六、关键指标速查与判断依据

以下为AWR/ASH联合诊断中最常用的判断依据,可作为日常排查的参考:

  • DB CPU / DB Time > 80%:CPU密集型,优先检查Top SQL的CPU Time与执行次数。
  • DB CPU / DB Time < 50%:等待密集型,优先看Top Foreground Events。
  • db file sequential read 高:索引单块读多,检查索引选择性与回表次数。
  • db file scattered read 高:全表扫描或并行读,检查大表访问路径。
  • log file sync 高:提交频繁,检查应用提交策略与redo日志I/O。
  • enq: TX - row lock contention 高:事务冲突,用ASH blocking_session还原阻塞链。
  • library cache lock / pin 高:硬解析或DDL争用,检查共享池与绑定变量。
AWR的Top SQL按Elapsed Time排序时,可能被少量超长SQL主导;按Buffer Gets排序时,可能被高频小SQL主导。必须结合Executions与per Exec指标判断,避免误判优化对象。

总结来说,AWR提供“面”,ASH提供“点”,时间模型提供“比例”,三者结合才能从整体负载定位到分钟级拐点,再落到具体SQL与阻塞会话。实际诊断中,建议先看AWR的DB Time与DB CPU比例确定大方向,再用ASH按分钟聚合找到突变时刻,最后用blocking_session与sql_id锁定根因。这套路径适用于大多数“平均指标正常但用户报慢”的复杂性能故障。