rac gc buffer busy hash分区,固定节点运行

inst_id分区避免rac gc buffer busy

解决思路

原因/解决方法

  • 热点块(hot block)
    在AWR中Segments by Global Cache Buffer Busy 记录了访问频繁的gc buffer.
    解决方法可以根据热点块的类型采取不同的解决方法,比如采取分区表,分区索引,反向index等等。这点与单机数据库中的buffer busy waits类似。

  • 低效SQL语句
    低效SQL语句会导致不必要的buffer被请求访问,增加了buffer busy的机会。在AWR中可以找到TOP SQL。解决方法可以优化SQL语句减少buffer访问。这点与单机数据库中的buffer busy waits类似。

  • 数据交叉访问。
    RAC数据库,同一数据在不同数据库实例上被请求访问。
    如果应用程序可以实现,那么我们建议不同的应用功能/模块数据分布在不同的数据库实例上被访问,避免同一数据被多个实例交叉访问,可以减少buffer的争用,避免gc等待。

  • Oracle bug
    建议安装Oracle推荐的最新Patch Set和PSU。
    Patch set和PSU信息请参考:Oracle Recommended Patches – Oracle Database (Doc ID 756671.1)

通过ASH报告,我看到刚才系统HANG住的时候,主要的等待事件是buffer busy wait

Avg Active

Event Event Class % Activity Sessions

----------------------------------- --------------- ---------- ----------

buffer busy waits Concurrency 72.55 9.31

enq: HW - contention Configuration 14.21 1.82

gc buffer busy Cluster 7.67 0.98

CPU + Wait for CPU CPU 2.13 0.27

-------------------------------------------------------------

看样子是由于热块冲突导致系统HANG住的,而且高水位推进相关的锁等待也很严重,应该系统中有大量的数据插入。从这个情况看想简单的通过调整参数来解决问题是不大可能了,必须从应用的特点去分析,才有可能找到解决方案。于是我问郝经理:"你的应用是什么样的,是不是有大量的插入操作?"

郝经理告诉我这个系统是企业应用集成系统,是从其他系统中接收数据,经过处理后存储在本系统中,供经营分析系统使用。目前的压力测试中的主要操作是对34张大表进行大批量的数据插入,其中还有张表里带LOB字段。

我和郝经理研究了一下,对这些数据的访问,除了大规模的数据插入外,一般来说是按主键访问,或者按某些分类条件的小范围查询,每次范围查询顶多占整个表数据量的几万分之一,并且范围查询的比例相对较小,仅占整个系统查询数量的10%不到。这种情况是典型的可以使用HASH分区的,通过HASH分区既可以解决BUFFER BUSY WAIT的问题,又可以解决enq: HW -contention的问题。于是我建议郝经理把这几张表按照主键MSG_IDhash分区,先尝试一下16个分区,看看能不能解决问题。

按照我的建议做了HASH分区后,压力测试重新开始了,这回看样子效果很不错,从em控制台上看,buffer busy wait等待已经少了很多,而且enq: HW - contention等待也消失了。


Avg Active

Event Event Class % Activity Sessions

----------------------------------- --------------- ---------- ----------

gc buffer busy Cluster 90.69 14.83

gc current request Cluster 6.05 0.99

CPU + Wait for CPU CPU 1.05 0.17

目前的主要等待是gc buffer busy,由于目前在连个节点上各有40个并发插入的会话在进行数据插入,因此全局BUFFER等待的问题肯定是存在的,目前压力测试已经进行了1个多小时了,从em观察到的情况来说系统一直还很平稳。现在的时间已经是中午的12点半了,郝经理建议我们先去吃饭,等吃完饭回来再看看结果。

在下面的食堂里简单吃了点东西,我们就回到了办公室,现在是下午的1320分了,压力测试也已经开始了差不多2个小时了,系统的状态依然和我们吃饭前一样,还没有出现hang住的现象。不过从平均事务响应时间来看,现在比一个小时前要慢了40%,这是一个十分不好的现象,如果这种趋势延续下去的话,很可能会再次出现系统HANG住的现象。

看着郝经理他们兴奋的样子,我给他们泼了盆冷水,可能问题还是没彻底解决,从目前的趋势上看,有可能系统还会HANG住。我正在和他解释为什么我会有这种预感,突然从EM上看到系统活跃情况突然下降了,系统可能又HANG住了。

我连忙做了一个3级的hanganalyze,从trace上看:

Open chains found:

Chain 1 : :

<0/786/9/0xff010e58/9474/gc buffer busy>

-- <0/785/26/0xff011e38/9512/gc current request>

Chain 2 : :

<0/791/32/0xff00e6a8/9404/gc buffer busy>

-- <0/785/26/0xff011e38/9512/gc current request>

Chain 3 : :

<0/792/12/0xff00ee98/9408/gc buffer busy>

-- <0/785/26/0xff011e38/9512/gc current request>

Chain 4 : :

<0/794/19/0xff00d6c8/9334/gc buffer busy>

-- <0/785/26/0xff011e38/9512/gc current request>

大量的gc buffer busy导致了大量的gc current request等待。很多会话由于gc buffer busyHANG住一段时间,实际上系统并没有真正的HANG住,而是变得十分慢而已。不过如果这种情况的范围如果扩大的话,就会导致应用软件出现问题,产生丢失数据的现象。过了几分钟,郝经理那边也确认了这次系统HANG住,1号节点的应用被挂起了35秒钟,丢失了70多条数据,实验再次失败了。

看样子GC BUFFER BUSY最终还是导致了严重的问题。由于他们的应用没有针对RAC进行优化,同一个应用分别在2个节点上跑,所以导致了严重的节点间的热块冲突。也许把这个应用集中在一个节点上就能够解决问题。我把我的想法和郝经理说了,郝经理觉得可以试试,不过他们的系统发展起来特别快,所以从最初做设计的时候就考虑要使用RAC,而且今后不仅要支持双节点,还可能扩展为3节点甚至4节点。目前的业务有可能单节点能够支持,不过今后一个节点可能无法支撑所有的负载。

我考虑了一下,刚才应用放在两个节点上跑的时候,两个服务器的CPU使用率都已经超过60%了,如果跑在一个节点上,确实负载挺大的,一个节点还真有可能支持不了,更不要说今后系统扩展性的问题了。看样子必须从底层结构上进行调整了。我问郝经理,如果在表里面加一个字段,并且每次插入的时候给这个字段赋一个常量,这样修改程序他们的工作量大不大。郝经理想了想说应该问题不大,修改一下也就是10分钟的事情。

我说如果这样就好办,我们可以对表结构做一个调整,来彻底解决这个问题。我们重新对表进行分区,使之成为一个复合分区表,在这张表上加入一个字段inst_id,也就是实例编号,这个字段作为主分区字段,按照这个分区做范围分区后,再设置msg_idhash分区。调整后的表结构如下:

CREATE TABLE QSTORE

(

MSG_ID VARCHAR2(64 BYTE) NOT NULL,

DOCE_ID VARCHAR2(100 BYTE) NOT NULL,

DOC_KEY VARCHAR2(100 BYTE) NOT NULL,

BUS_NAME VARCHAR2(100 BYTE),

MODULE_NAME VARCHAR2(100 BYTE),

CATEGORY VARCHAR2(64 BYTE),

SUB_CATEGORY VARCHAR2(64 BYTE),

DOC_SIZE NUMBER(11) DEFAULT 0,

CREATE_TIME DATE,

MODIFY_TIME DATE,

EXPIRED_TIME DATE,

DOC_FLAG NUMBER(2),

Inst_id number

) initrans 20 pctfree 20 tablespace TS_DATA_EAI

PARTITION BY RANGE(inst_id)

SUBPARTITION BY HASH(msg_id) SUBPARTITIONS 8

(PARTITION p1 VALUES LESS THAN (2),

PARTITION p2 VALUES LESS THAN (3));;

Inst_id的值就是插入进程连接到的实例的ID,这样调整后,在1号节点上插入的数据将全部被插入到inst_id=1的分区,插入操作就不会产生大量的global cache request了。这种做法也是在RAC上解决GC BUFFER BUSY的常用方法之一。

郝经理很快就明白了我的意思,上楼去安排开发人员修改应用了。我也趁机休息休息,准备下面的测试了。这时候老储的电话又打了进来,那个问题终于解决了,通过hcheck对数据字典进行检查,发现有一张表的数据字典出现了不一致,在tab$中还有记录,但是在obj$里的记录缺失了,查找这个表空间中有什么对象找不到,但是删除tablespace的时候又删除不了。把tab$中的数据手工删除后,表空间就成功的删除了。

刚和老储通完电话,郝经理的电话就打了进来,他说应用已经修改好了,他已经开始了测试,大概10分钟后压力就会加载到数据库上,让我监控一下有没有什么问题。从测试刚开市的情况看,gc buffer busy基本上消失了,系统也比较平稳,从EM的监控情况来看,系统一切都很平稳,系统已经运行了一个多小时,从awr报告来看,现在的平均事务响应时间,和系统刚刚启动时差别不大,并且gc buffer busy 等待事件也已经不在top 5等待时间里了。看样子通过这么优化,系统趋于稳定了。郝经理建议我们先回去,压力测试做一晚上,明天上午10点再来看结果。如果那时候发现系统一切正常,那么说明问题已经解决了。

select t.INSTANCE_NUMBER into p_inst_id from v$instance t

通过procedure进行插入,在执行的开始,取得instance_id

 

gc buffer busy: 产生这个等待事件是由于实例间产生热块争用造成的,要解决这个问题有两种方法:

第一、分割应用:把应用集中在一个节点上运行

第二、对表添加一个字段,这个字段存放实例的id号,如果在节点1执行的那么存放节点1的实例id号, 如果在节点2执行的那么存放节点2的实例id,在执行之前首现获取实例的id号。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值