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

一个ORACLE BUG 引发的gc cr/current request等待

4328

第一章 故障概述

某日,客户反馈XX系统存在大量enq: TX - index contention阻塞,即:索引分裂问题。影响了系统正常的业务活动。在早高峰发现上述问题后,为了及时缓解业务应用,通过杀掉阻塞会话的方式,来解决了对应问题。在阻塞结束后,对XX系统出现的异常问题进行分析,以确定出现问题的根本原因。

数据库版本:ORACLE 11.2.0.4

经过分析,出现上述异常的根本原因是由于触发了ORACLE 11.2.0.4的BUG
Bug 24555417 - Sessions Waiting On ‘gc buffer busy acquire’=> { ‘gc cr request’ | ‘gc current request’ } With No Blocker (Doc ID 24555417.8)

MMON进程异常报错,在内存中留下了pin锁,此后节点2在插入数据时触发了的索引分裂,在索引分裂操作过程中通过GC获取源端节点1上的索引块时,和节点1内存的Pin锁冲突,导致节点2的索引分裂和gc buffer busy acquire等待长时间HANG住,从4点24开始一直持续到9点之后,直到后续运维人员KILL会话,把这个HANG的问题解决。

第二章 故障分析

2.1 故障现象

在业务高峰期8点左右出现大量enq: TX - index contention索引分裂等待事件。问题持续1一个多小时直到杀会话后解除。

查看问题时段的AWR报告:

image.png

可以看到主要的问题是索引分裂现象。且平均延时非常高。查看索引分裂的对象分布:

image.png
image.png
image.png

对比了多个时段的报告分析,其中索引分裂的程度并不严重。根节点没有进行分裂,只是对分支节点进行,且分裂程度并不频繁。

这里就很奇怪,分裂量级并不严重,为何会出现如此大量的分裂问题甚至导致数据库HANG住呢?

分析历史的活动会话累计,可以追述故障起点在当日的4点23分左右就已出现。

image.png

2.2 故障根源分析

分析对应时段的活动会话,可以看到主要在16日4点24分49秒时,出现大量的索引分裂及GC等待事件。

image.png

发生等待在同一个对象上面。

image.png

而这里索引分裂,伴随着大量GC等待,也是合理的。索引分裂过程中,如果内存块在另一节点,需要通过gc驱动索引块完成分裂动作。

查看相应事件的P1/P2:

select instance_number,
       event,
       p1,
       p2,
       count(*) cn,
       max(to_char(sample_Time, 'yyyymmddhh24miss')) max_time,
       min(to_char(sample_Time, 'yyyymmddhh24miss')) min_time
  from dba_hist_active_sess_history
 where sample_time >= to_date('202208160300', 'yyyymmddhh24mi')
   and sample_time < to_date('202208161000', 'yyyymmddhh24mi')
   and event = 'gc buffer busy acquire'
 group by instance_number, event, p1, p2
having count(*) > 5
 order by cn desc

image.png

主要为2节点的gc buffer busy acquire事件,从4点一直持续到早上9点。且阻塞在同一个文件、块号上面。

问题时点主要在执行SQL: c6v5t48b4pj6x

image.png

其对象也是在索引IDX_表名__FINISH_TIME上面。
查看阻塞链:

col lock_chain for a75
col EVENT_CHAIN for a50
col first_seen for a18
col last_seen for a18
col BLOCKING_HEADER for a10
with ash as (
select *
  from gv$active_session_history
 where sample_time>=to_date('2022-08-16 08:30:52','yyyy-mm-dd hh24:mi:ss')
   and sample_time< to_date('2022-08-16 11:30:52','yyyy-mm-dd hh24:mi:ss')),
ash2 as (
select sample_time,inst_id,session_id,session_serial#,sql_id,sql_opname,
       event,blocking_inst_id,blocking_session,blocking_session_serial#,
       level lv,
       connect_by_isleaf isleaf,
   sys_connect_by_path(inst_id||'_'||session_id||'_'||session_serial#||':'||sql_id||':'||sql_opname,'->') lock_chain,
       sys_connect_by_path(EVENT,',') EVENT_CHAIN ,
       connect_by_root(inst_id||'_'||session_id||'_'||session_serial#) root_sess
  from ash
 --start with event like 'enq: TX - row lock contention%'
 start with blocking_session is not null
 connect by nocycle 
        prior blocking_inst_id=inst_id
    and prior blocking_session=session_id
    and prior blocking_session_serial#=session_serial#
    and prior sample_id=sample_id)
select lock_chain lock_chain,
       case when blocking_session is not null then blocking_inst_id||'_'||blocking_session||'_'||blocking_session_serial# else inst_id||'_'||session_id||'_'||session_serial# end blocking_header, EVENT_CHAIN,
       count(*) cnt,
       TO_CHAR(min(sample_time),'YYYYMMDD HH24:MI:ss') first_seen,
       TO_CHAR(max(sample_time),'YYYYMMDD HH24:MI:ss') last_seen
   from ash2
  where isleaf=1
group by lock_chain,EVENT_CHAIN,case when blocking_session is not null then blocking_inst_id||'_'||blocking_session||'_'||blocking_session_serial# else inst_id||'_'||session_id||'_'||session_serial# end
having count(*)>1
order by first_seen, cnt desc;

image.png

最终的阻塞者是9117会话。且SQL: c6v5t48b4pj6x被8218所阻塞,8218又被9117阻塞。依次的等待事件是:索引分裂enq: TX - index contention、gc buffer busy acquire、gc current request。

继续查看该时点的阻塞者:

image.png

阻塞会话9117。
image.png

而9117会话等待事件为gc current request。该等待同样持续到早上才结束。
image.png

4点开始,持续到早上9点。且没有阻塞者。
image.png

通过上述跟踪,源头SQL等待gc buffer busy acquire。被会话9117所阻塞,而阻塞者的等待事件为gc current request。且无阻塞者。

这种现象与ORACLE的一个BUG较为符合。
image.png

根据BUG描述,在11204版本会出现。
image.png

且MMON中会出现如下现象:
image.png

分析两节点的MMON日志:
image.png

在1节点的MMON日志中,出现了对应的12751错误。进一步印证了我们前面的分析。

2.3 故障解决

问题是通过杀掉索引分裂相关的会话来解决的。

后续在发现会话长时间出现gc cr request 或gc current request等待时,根据p1和p2判断是否HANG在同一个数据块的读取过程中,并一直持续的现象后。可以检查mmon进程的trace,是否存在ORA-12751的报错。

如果上述现象均符合,证明确实触发了相应的BUG。
由于当前版本已是11g最新版,无法通过补丁方式解决,可参照MOS中的解决方案,快速kill mmon进程来解决。

第三章 解决方案及总结

明确了问题原因,下面分析解决方案:

  1. 通过kill mmon进程来解决:
    后续在发现会话长时间出现gc cr request 或gc current request等待时,根据p1和p2判断是否HANG在同一个数据块的读取过程中,并一直持续的现象后。可以检查mmon进程的trace,是否存在ORA-12751的报错。
    如果上述现象均符合,证明确实触发了相应的BUG。
    由于当前版本已是11g最新版,无法通过补丁方式解决,可参照MOS中的解决方案,快速kill mmon进程来解决。

  2. 通过规范插入业务在同节点来降低GC等待的产生,从而降低触发BUG的概率。
    经过了解,相应语句的大量插入在每日均有进行,且不区分节点。如能控制相应插入仅在同一节点进行,则对新插入的数据块不会产生如此多的GC类等待事件。也降低了触发该BUG的几率。

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

评论