性能调整一则:buffer busy waits导致主要issue

http://blog.itpub.net/post/37595/467355

这是一套生产环境的3节点RAC环境,RHEL3+9208,突出等待事件为buffer busy wait及cluster wait。

top,vmstat,free过后发现系统较为空闲状态,抓statspack:

Cache Sizes (end)
~~~~~~~~~~~~~~~~~
Buffer Cache: 1,312M Std Block Size: 16K
Shared Pool Size: 448M Log Buffer: 1,024K

Load Profile
~~~~~~~~~~~~ Per Second Per Transaction
--------------- ---------------
Redo size: 103,989.15 5,199.31
Logical reads: 4,307.61 215.37
Block changes: 670.76 33.54
Physical reads: 6.72 0.34
Physical writes: 14.18 0.71
User calls: 329.68 16.48
Parses: 128.77 6.44
Hard parses: 8.52 0.43
Sorts: 18.64 0.93
Logons: 0.03 0.00
Executes: 320.35 16.02
Transactions: 20.00

% Blocks changed per Read: 15.57 Recursive Call %: 55.47
Rollback per transaction %: 2.37 Rows per Sort: 21.30

Instance Efficiency Percentages (Target 100%)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Buffer Nowait %: 99.88 Redo NoWait %: 99.99
Buffer Hit %: 99.84 In-memory Sort %: 100.00
Library Hit %: 97.90 Soft Parse %: 93.38
Execute to Parse %: 59.80 Latch Hit %: 99.93
Parse CPU to Parse Elapsd %: 98.16 % Non-Parse CPU: 89.86

因应用改动起来太大一直没有使用绑定变量,软解析不高,目前强制cursor_sharing为force,shared_pool_size有些偏大,在线将其改小这种做法当然不可取,db_cache_size在后面的advice看起来处于合适大小状态。

Top 5 Timed Events
~~~~~~~~~~~~~~~~~~ % Total
Event Waits Time (s) Ela Time
-------------------------------------------- ------------ ----------- --------
global cache cr request 147,324 698 19.66
buffer busy global CR 7,435 682 19.22
global cache null to x 85,665 613 17.27
CPU time 574 16.17
buffer busy global cache 8,012 221 6.22

从owi方面看起来是符合之前讲的主要issue为buffer busy waits及RAC相关的wait的。

分析:

目前MLB21上的主要等待事件为buffer busy wait,等待类别为data block,实际上因data block而触发的buffer busy wait等待事件下面两类: 1、一种是高并发会话在对相同的对象执行DML,同时db_block_size尺寸较大(因同一个块包含更多的行)

从抓取到的二条TOP合此类型(UPDATE&INSERT),较为合适的方法就是增大PCTFREE。

2、另外就是多个session并发请求相同的数据块,但因该数据块不在buffer_cache中而必须从磁盘读取,处理这种情况,oracle会只让其中一个sesion进行磁盘读取,此时其它session等待块从磁盘上读取进buffer_cache而抛出buffer busy wait等待事件。

这种情况也存在于当前环境中,从抓取到的第3条语句,表现为执行较为频繁且伴随有db file sequential read等待事件,可以先试着先优化TOP N逻辑读的SQL。

再比对一下,发现导致buffer busy wait的SQL语句与导致cluster wait的SQL语句一模一样。

于是问题清晰了,当前DB环境的block_size为16k,RAC环境下的OLTP再加上那几个超频繁被执行update、insert的大表操作下,显得有些惨不忍睹,当前那几个表的pctfree为10,准备加大到30左右,index的pctfree低于50会导致索引走范围扫描,且快速全局扫描会较慢。
上面提到的第2种buffer busy waits会造成少量的db file scattered read(即oracle允许其中一个session去磁盘读取数据块,当然,这个动作也有可能是db file sequential read)和大量的db file sequential read(即其他session会对读进来后的数据块进行逻辑读取),需要去调优statspack中的TOP N的逻辑读。

 

 

 

 

之前遇到的buffer busy waits的问题在所做的一些变动后,情况下降许多,但问题依然存在。
因为我们的环境中遇到的buffer busy waits为data block类型,识别码为220,让人直接想到的就是,高并发的DML是导致这个环境buffer busy waits的主因。(额外附注一下:当块被读到sga后,若有session想读取或者修改它,必先获取cache buffers chains锁存器以遍历该缓冲区链而找到所必需的缓冲区头,然后,根据session所请求的类别来以共享模式或者独占模式来pin住该缓冲区头,然后才可以进行读取或者修改,pin住后然后释放cache buffer chains锁存器)。

至于出现的global null to x 和global cr request之类的cluster wait,跟我们的应用较为相关,频繁的相同的DML动作分布在三个不同的节点(RAC环境为4节点),当修改其中一个节点SGA里的一个块后,其他节点同样有这个动作,9i的cache fusion会根据其他请求节点的GCS请求生成pi块到对应请求节点,因为session的pin动作是1:1的(pin:对象块),且9i默认pi块是6个,所以,这是目前环境中造成cluster wait的主要原因,再深入分析一下,这也跟block_size有较大原因,若一个块中含有的行不多,就算有此类buffer busy waits 220识别码的等待,也不会是非常突出的。不行的是,这个db环境的db_block_size不知是谁设的,大小为16K。

解决方法:
1、减少块中的行数(可增加pctfree,若块大小较大,应该收效甚微)
2、将client连接节点的操作进行分类,比如将那些造成并发update的应用都连接至同一个节点,当然,这样对rac的failover挑战又提高到新的一个层面,比如若这个节点crash掉,整个业务的流程基本也被破坏掉。

你可能感兴趣的:(buffer)