Oracle 等待事件那么多,怎么记才有用?

举报
Lucifer三思而后行 发表于 2026/10/15 09:27:17 2026/10/15
【摘要】 前言最近在分析一套 Oracle 19c RAC 数据库的性能问题,业务反馈某个生产系统偶尔出现接口超时。根据业务反馈的异常时间段,抓取了两份 AWR 报告。先看了 DB Time、CPU、Load Profile,整体负载并不高。两个实例的平均 AAS 都在 1 ~ 2 左右,CPU 也比较空闲。继续往下看,就到了等待事件:可以看到有很多等待事件:db file sequential r...

前言

最近在分析一套 Oracle 19c RAC 数据库的性能问题,业务反馈某个生产系统偶尔出现接口超时。

根据业务反馈的异常时间段,抓取了两份 AWR 报告。先看了 DB Time、CPU、Load Profile,整体负载并不高。两个实例的平均 AAS 都在 1 ~ 2 左右,CPU 也比较空闲。

继续往下看,就到了等待事件:

AWR 等待事件示意图

可以看到有很多等待事件:db file sequential read、read by other session、log file sync、gc cr grant 2-way……

Oracle 的等待事件非常多,尤其是 RAC 环境下,各种 gc 开头的事件,看着差不多,实际含义却不完全一样。

刚开始接触 AWR 时,我也想过把常见的等待事件整理出来,方便平时查阅。但后来发现,单纯记住事件名称和含义,实际帮助并没有想象中那么大。

比如看到 db file sequential read,知道它是单块读,但到底是存储响应慢,还是 SQL 读取的数据太多?光知道事件的定义,显然还不够。

所以这篇简单聊聊,我平时是怎么理解和记忆 Oracle 等待事件的。

一、先从名字入手

Oracle 很多等待事件的名称,其实已经告诉了我们大致的排查方向。

关键词 大致方向
db file 数据文件 I/O
direct path 直接路径 I/O
log file Redo、日志写入、事务提交
enq 锁、队列资源争用
gc RAC Global Cache
library cache 共享池对象相关
cursor 游标相关
read by other session 等待其他会话读取数据块

当然,这种分类并不严谨,只是方便平时快速判断。

比如 gc current block 2-way,一看 gc 就知道和 RAC 的 Cache Fusion 有关;enq: TX - row lock contention 通常要往事务锁的方向排查;而 log file sync,则主要关注事务提交和 Redo 写入。

这样至少能先确定排查方向,至于具体的等待机制、参数含义,遇到了再进一步查也不迟。

二、I/O 相关的等待,先记这几个

最常见的三个:

db file sequential read
db file scattered read
direct path read

db file sequential read 主要是单块读,常见于索引扫描、ROWID 回表等操作;db file scattered read 主要是多块读,通常与全表扫描有关;direct path read 则是直接路径读取,大表扫描、并行查询时比较常见。

这几个事件都比较常见,但实际分析时不能只看事件名称。

比如 db file sequential read 排在 AWR 等待事件前面,很多人第一反应就是磁盘 I/O 有问题,其实不一定。

这次数据库的 AWR 中,两个实例的 db file sequential read 平均等待时间都不到 1ms,单次 I/O 响应并不慢。但继续分析 SQL 后发现,有些 SQL 每次执行需要读取大量数据块,虽然单次读取很快,累计下来耗时依然很长。

其中一条 SQL 的统计信息如下(数值已做近似处理):

SQL_ID          已隐藏
执行次数        少于 10 次
平均执行时间    超过 100 秒
平均逻辑读      数十万块
平均物理读      十万块以上

SQL 访问的是一张业务明细表,主要根据多个业务条件进行汇总查询。

执行计划如下(对象名称已脱敏):

SORT GROUP BY NOSORT
  INLIST ITERATOR
    TABLE ACCESS BY INDEX ROWID BUSINESS_TABLE
      INDEX RANGE SCAN IDX_BUSINESS_01

从执行计划来看,这条 SQL 虽然走了索引,但单次执行仍然产生了大量逻辑读和物理读。

其中 INDEX RANGE SCAN 预估返回百万级记录,后续还需要通过 ROWID 回表。这里的行数是优化器估算值,实际扫描了多少,还需要结合执行统计进一步确认。

不过,单从 AWR 的数据来看,这条 SQL 的读取量已经明显偏高。

这也说明,db file sequential read 等待较多,并不一定是存储性能问题,也可能是 SQL 本身访问了太多数据块。所以分析 I/O 等待时,除了关注单次 I/O 延迟,还要结合 SQL 的逻辑读、物理读和执行计划一起看。

db file scattered read 和 direct path read 也是一样,重点还是看实际扫描了多少数据,以及这些读取是否必要。

毕竟,走了索引不代表 SQL 一定快,全表扫描也不代表执行计划一定有问题。

三、Commit 相关的等待

这类先熟悉两个就够了:

log file sync
log file parallel write

log file sync 主要是前台会话等待事务提交完成,log file parallel write 则是 LGWR 写入 Redo 日志时产生的等待。

这两个事件通常需要结合起来分析:如果 log file sync 和 log file parallel write 的平均等待时间都明显升高,就需要重点检查 Redo 日志写入延迟。

如果 log file sync 较高,而 log file parallel write 比较正常,就不能直接判断是存储问题,还需要结合 Commit 次数、LGWR 调度等情况进一步排查。

另外,应用频繁提交事务也值得关注:比如每处理一条记录就执行一次 Commit,即使单次提交耗时不高,累计等待时间也可能比较明显。

因此,分析 log file sync 时,不能只看累计等待时间,还要结合平均等待时间、提交频率以及 log file parallel write 的表现,判断究竟是提交过于频繁,还是 Redo 写入本身存在延迟。

四、锁和并发相关的等待

最常见的是:

enq: TX - row lock contention

比如会话 A 更新一条记录后一直没有提交,会话 B 又来修改同一条记录,就可能产生等待。

不过,enq: TX - row lock contention 并不一定都是普通的行锁阻塞,也可能涉及唯一键冲突、ITL 资源不足等情况。实际排查时,可以先通过 GV$SESSION 查看阻塞会话,再结合事务信息、等待模式和 SQL 进一步分析。

另外,还有一个比较常见的等待事件:

read by other session

这个事件和行锁等待不是一回事,它表示当前会话需要读取的数据块正在由其他会话读取,因此需要等待对方完成 I/O。

前面提到的那条高读取量 SQL,在 ASH 中就出现了这类等待。

所以碰到并发等待时,还是要先区分具体的等待资源,enq: TX - row lock contention 重点排查事务锁,而 read by other session 则需要关注并发读取、热点数据块以及相关 SQL 的 I/O 情况。

五、RAC 里面的 gc 等待

在 RAC 环境中,gc 开头的等待事件也比较常见,主要与实例之间的 Global Cache(全局缓存)协调有关。

比如:

gc cr block 2-way
gc current block 2-way
gc cr grant 2-way

这几个等待事件名称比较相似,可以拆开来看:

  • gc:Global Cache,RAC 全局缓存。
  • cr:Consistent Read,一致性读。
  • current:当前版本的数据块。
  • block:通常涉及跨实例数据块传输。
  • grant:主要涉及全局缓存访问授权,不一定需要传输数据块。

至于后面的 2-way、3-way,主要用于区分不同的消息交互路径。

需要注意的是,RAC 本身就存在跨实例数据块访问,因此出现 gc 等待并不代表集群有问题。

实际分析时,我一般会结合等待次数、平均等待时间和数据块传输量来判断。如果等待时间明显偏高,再进一步检查相关 SQL、热点对象、跨实例访问情况以及私有网络延迟。

六、等待事件到底怎么看?

前面说了这么多,其实平时看 AWR,我主要关注以下几个指标:

指标 含义
Waits 等待次数
Time(s) 累计等待时间
Avg wait 平均每次等待时间
% DB time 累计等待时间占 DB Time 的比例

这里需要注意,等待次数多不一定代表问题严重,平均等待时间高也不一定说明对数据库整体影响很大。

比如一个事件发生了 100 万次,平均等待 0.1ms,累计等待时间为 100 秒;另一个事件只发生了 100 次,但平均等待 2 秒,累计等待时间反而达到 200 秒。

因此,分析时需要结合等待次数、累计等待时间和平均等待时间,不能只看其中一个指标。

另外,还要注意 AWR 的统计时间范围。这次数据库的 AWR 覆盖了数小时,两个实例的平均 AAS 都比较低,db file sequential read 的平均等待时间也不到 1ms。

但业务反馈的是偶发超时,长时间窗口的平均数据很可能掩盖短时间内的性能波动。

对于这种情况,还需要结合业务异常的具体时间,通过 ASH 查看当时的活跃会话、SQL_ID 和等待事件,进一步确认问题发生在哪个环节。

七、遇到不认识的事件怎么办?

这个很简单,直接查。

Oracle 自己就提供了等待事件信息:

SELECT name,
       wait_class,
       parameter1,
       parameter2,
       parameter3
FROM v$event_name
WHERE name = 'db file sequential read';

查询结果:

NAME                     WAIT_CLASS  PARAMETER1  PARAMETER2  PARAMETER3
-----------------------  ----------  ----------  ----------  ----------
db file sequential read  User I/O    file#       block#      blocks

可以查看事件所属的 Wait Class,以及 P1、P2、P3 对应的参数含义。

如果想看看数据库当前累计等待时间较高的事件:

SELECT event,
       total_waits,
       ROUND(time_waited_micro / 1000000, 2) time_sec,
       ROUND(
         time_waited_micro /
         NULLIF(total_waits, 0) / 1000, 3
       ) avg_wait_ms
FROM v$system_event
WHERE wait_class <> 'Idle'
ORDER BY time_waited_micro DESC
FETCH FIRST 20 ROWS ONLY;

下面是部分常见等待事件的示例输出(演示数据,非生产查询结果):

EVENT                          TOTAL_WAITS   TIME_SEC  AVG_WAIT_MS
-----------------------------  ------------  --------  -----------
db file sequential read           12500000    8750.00        0.700
log file sync                      3200000    4800.00        1.500
gc current block 2-way            4800000    2400.00        0.500
log file parallel write           2500000    2500.00        1.000
direct path read                   1800000    2700.00        1.500
read by other session              1500000    1200.00        0.800
gc cr block 2-way                  2100000    1050.00        0.500

需要注意的是,V$SYSTEM_EVENT 记录的是实例启动以来的累计等待统计,并不是指定时间段的数据。如果要分析某个历史时段的性能问题,还是需要结合 AWR、ASH 进行排查。

对于不熟悉的等待事件,可以先通过 V$EVENT_NAME 查看事件分类和等待参数,再结合具体 SQL、会话及执行计划分析。平时遇到有代表性的案例,也可以顺手记录一下,后续碰到类似问题直接参考即可。

最后

Oracle 等待事件虽然很多,但平时真正经常遇到的也就那么一些。像 I/O、Commit、锁和 RAC 相关的等待,结合实际故障多分析几次,基本就熟悉了。

其他不常见的事件,遇到了再查也不迟。关键还是要结合等待时间、SQL 和执行计划,判断问题到底出在哪里,而不是单纯根据等待事件的名称下结论。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。