暂无图片
暂无图片
2
暂无图片
暂无图片
暂无图片

一次直接路径读引起的IO异常分析处理经过

原创 听见风的声音 2024-11-13
803

1 异常现象的发现

这次IO异常发生在一个业务系统的生产数据库上,在每天的早上的例行巡检时发现这个Oracle实例(RAC集群中的一个实例)的IOPS指标异常增长后有不间断的连续出现峰值。指标的时间趋势图如下:
IO异常.jpg
图中横轴显示的时间以小时为单位,IOPS指标的最大值是6000左右。可以看出,在10点之前,IOPS指标的峰值只是间或出现,大概是每小时一次,自10点以后,IOPS峰值出现密度明显加大。
这个RAC集群使用的是传统的基于机械盘的磁盘阵列,这个数量的IO对存储的压力还是相当大的,因此这个异常也忽略不得,必须处理掉。

2 异常现象的分析

从图中可以看出,这次异常出现的时间已经持续了一个小时以上,持续时间跨过了一个完整的AWR报告采样周期。先取一下这个采样周期的AWR报告看一下吧。报告取出,打眼一看,数据库的负载、IO、等待事件等指标都处于正常范围之内,IO异常还没有影响到数据库的性能。既然是IO异常,接着就看一下是不是有sql语句在执行时发生了大量的物理读。找到AWR报告的SQL ordered by Reads 部分,发现有一条SQL语句的物理读明显异常。
逻辑读异常的语句.jpg
可以看到,图中第一条SQL语句的物理读明显异常,这段时间的Total Disk Reads是15253726,这条语句这个时间段的物理读是15176980,占了99.5%。这个时间段内这条语句执行了60次,每次物理读是252949.67次,一次执行发生25万多次的物理读,首先怀疑的是这条语句是不是执行了全表扫描,通过这条语句的执行计划确认了这一点。
再看这条语句的执行的逻辑读,同物理读次数完全相同。通过Oracle数据库语句的执行原理可以知道。一条语句即使执行了全表扫描,通常第一次执行时物理读次数比较多,可能同逻辑读次数相同(这里不包含系统调用的次数)。等到数据读到缓冲池之后,基本上就不会发生物理读了。
这条语句每次执行都要进行这么多的物理读,极大可能是执行了直接路径读的原因。这个可以通过检查这条语句的等待事件来确认,执行下面的SQL语句查询这条语句的等待事件:

SQL> select to_char(SAMPLE_TIME,'YYYY-MM-DD hh24:mi:ss') SAMPLE_TIME,sql_id,EVENT,TIME_WAITED from v$active_session_history where sql_id= '1h50ks4ncswfn' SAMPLE_TIME SQL_ID EVENT TIME_WAITED ------------------- ------------- ---------------------------------------------------------------- ----------- 2024-11-13 11:59:26 c8**********u direct path read 0 2024-11-13 11:59:25 c8**********u direct path read 0 2024-11-13 11:59:24 c8**********u direct path read 4419 2024-11-13 11:59:23 c8**********u direct path read 4875 2024-11-13 11:59:22 c8**********u direct path read 6572 ......................................................................................................... 2024-11-13 10:05:21 c8**********u direct path read 1435 2024-11-13 10:05:20 c8**********u direct path read 2839 2024-11-13 10:05:19 c8**********u direct path read 1235

可以看到,这条语句的执行过程中一直在等待直接路径读事件,直接路径读不经过SGA的数据缓冲池,因而物理读非常大。

3 关于直接路径读

Oracle的直接路径读网上介绍的文章很多了,这个特性的推出是为了解决大量数据读入缓冲池会造成对SGA的冲击的问题,在Oracle 11g,12c等版本中这个特性默认都是打开的。直接路径读不经过SGA的缓冲池,每次都从磁盘读入数据到会话的PGA区,如果存储的性能比较差,会对存储造成较大的压力,因此,这个特性在很多场合下dba都会手动关闭。直接路径读的开启关闭是由隐形参数_serial_direct_read控制的,用下面的SQL查询这个隐形参数的设置

SQL> l 1* select i.KSPPINM,v.KSPPSTVL from x$ksppi i inner join x$ksppcv v on v.indx=i.indx where i.KSPPINM='_serial_direct_read' SQL> / KSPPINM KSPPSTVL -------------------------------- -------------------------------- _serial_direct_read auto

这个隐形参数的默认设置是auto,在这种情况下,需要同时符合下面三种情况,才能触发直接路径读:

  • 表大小超过 _small_table_threshold 隐含参数设置的阀值
  • 表在buffer cache块数低于50%
  • 表脏块数低于的25%
    如果发生了直接路径读,AWR报告里以下部分会显示出来:
    数据库tablescan.PNG
    发生直接路径读的分段也会在awr报告中Segment Statistics的Segments by Direct Physical Reads中显示出来。
    如果存储性能不理想或者担心运维不到位,这个特性也可以关闭,使用下面的语句
alter sytem set “_serial_direct_read”=never scope=both sid=’*’;

4 处理办法

这个case中,直接路径读并没有影响到性能,考虑到关闭可能对缓冲池的影响,还是从SQL语句及数据的优化来处理,清理了相关表的历史数据,同时在这张表上创建了索引,避免了全表扫描。

最后修改时间:2024-11-15 08:40:10
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论