Oracle Deep Internals | 第一课
2017-08-09
IT系统性能问题诊断方法论| 第一课
2017-08-11

 

 

Buffer Busy waits

 

1. Basic Info

访问特定块的进程需要先获得特定块的Buffer Lock。假如要修改特定的块,需要以独占(Exclusive)模式获得的Buffer Lock。相反,只是要读取特定块需要以共享(Shared)模式获得 Buffer Lock。

如果进程A对块X已获取Buffer Lock的状态时,因进程B对同一个块不能以互换模式获取而进行Buffer Lock等待。这时发生的就是buffer busy wait事件。

Buffer bus wait最常见的情况是在多个进程对同一个块进行Insert或者Update的情况。对块进行Insert或者Update的时候,要求以独占模式获取Buffer Lock。多个进程同时对同一个块以独占模式获取Buffer Lock时会发生对Buffer Lock的争用,显示为buffer busy wait事件的发生。

 

2. Parameter & Wait Time

 

2.1 Wait Paremeters

buffer busy wats等待事件的等待参数如下。

P1:File#

P2:Block#

p3:在Oracle 10g表示的是块类(block class),在Oracle 9i表示的是Reason Code。

 

2.2 Wait Time

一般等待1秒。假如为了以独占模式获取Buffer Lock等待Buffer busy wait事件1秒后,再次获取时需要等待3秒。要读取特定块的会话必须获得Buffer Lock。

 

3. Check Point & Solution

因不同的块类而发生buffer busy waits事件的原因和解决方法如下。

数据块(块类=1

用户应用程序的多个会话对同一块执行修改的时,一般称这种块为热块(Hot Block)。解决热块的方法有以下几种。对用户应用程序进行修改:通过对应用修改使得多个会话不会同时对一个块进行修改。

  • PCTFREE值的调整:加大PCTFREE值,在一个块里的行数自然会减少,从而减少对块的争用。
  • 右倾索引的修改:索引键右倾斜会发生对索引叶节点的竞争。最具代表性的是利用序列(Sequence)值产生的键的值作为索引使用。这时可以利用反转索引(Reverse Index)使键值分散,从而减少争用。
  • 使用FLM时:使用FLM(Free List Management)的时候,在Storage属性中要设置充分大的FREELISTS属性值。FREELISTS的值是1的时候,因为会有多个进程对同一个块Insert而发生争用。FREELISTS值最好设置为同时执行Insert进程的最大值。
  • 分区(Partitioning):通过段的分区可以任意的分散块。如果通过使用像哈希分区(Hash Partition)技术把聚集在一个块上的块用物理方法随机分散到任意空间上,以此可以减少争用。

段头(段类=4

使用FLM的时候,在Storage属性中设置充分大的FREELISTS属性值。如果是在OPS或RAC的环境下,需要给FREELIST GROUPS设置跟实例个数一样的值。设置了FREELIST GROUPS属性值后,与段头块使用不同的FREELIST,所以会减少对段头块的争用。

位图(Bitmap)块(块类=8910

使用ASSM(Automatic Segment Space Management)时可能会发生三个阶段的位图块的争用。位图块中发生的块争用无法利用Oracle的调优而改善,而是要通过应用程序的修改, 减少过多的并发的DML。

ASSM中大规模的同时DML相比较FLM是会有更多一点的开销。但大部分情况下的这种开销是可以无视的。ASSM相比FLM提供更多优点,特别对RAC提供最佳性能。

回滚头块(块类=15+2*r

使用AUM(Automatic Undo Management)的时候在回滚头的块不会经常出现发生争用。使用手动模式的回滚段时,提供足量的回滚段数而减少回滚段的争用。

 

4. Event Tip

4.1 FLM

4.2 ASSM

5. Analysis Case

5.1 利用分散块减少buffer busy waits等待现象

下图是通过Maxgauge监控发生buffer busy waits事件的结果。

图buffer busy waits事件发生情况

分析buffer busy waits事件的发生原因分析结果可以确认,多个进程同时对同一个块修改的过程中,在数据块(Block class =1)上发生争用。即,以如下图的形式进行对特定表的Update操作就是原因所在。

为了随机分散块,而使用了如下的哈希分区。

— t_buffer_busy_waits 表

— 使用哈希分区将行分散到任意块中

CREATE TABLE t_buffer_busy_waits

(

id                            NUMBER,

name                         VARCHAR2(10)

)

PARTITION BY HASH(id) PARTITIONS 100;

下图是使用哈希分区后,通过Maxgauge监控同一应用程序的结果。可以确认buffer busy waits事件发生减少。

通过V$SYSTEM_EVENT视图可以确认改善前后buffer busy waits事件的等待时间,发现从4,120秒减少到了1,214秒。

 

5.2 因低效的SQL引起的Buffer Lock等待现象

因为在Oracle9i版本中Buffer Busy Wait(id130)事件在10g版本上更名为Read By Other Session,所以变成Read by other session的分析案例。

 

5.3 错误的FreeList属性值引起发生Buffer Busy Waits等待现象

需要分析的实例是发生了Actvie Seeion从维持平均2~30个,突然在特定的时段发生了剧增到300多个的现象。

Active Session趋势图如下,查看Active Session增加时段的等待事件目录来看,除了Idle事件(=SQL *Net Message..)之外Buffer busy waits事件是等待发生的最多的(1199秒)。

为了了解Active Session和Buffer Busy Waits事件等待的相关关系,确认两个指标的趋势图的结果,可以确认增加区域是一样的。

因此可以确认Active Session的剧增现象是因为发生了Buffer Busy Waits事件。

通过确认相应时间的Active Session List,等待Buffer Busy Waits事件的会话都是对SUBSCRIBE表进行INSERT,Buffer Busy Waits事件的P3值的ID是220。ID220是对同一个块进行修改时候发生的Buffer Lock争用现象。

因Insert而产生Buffer busy waits事件的争用大部分是因为错误的FREELISTS导致的。多个会话同时对同一个表进行Insert的时候,段会急剧扩张,这时相比在执行Insert的实际进程,空闲列的值过小时,发生Buffer Busy Waits。。

来确认一下实际等待Buffer Busy Waits事件的会话的Wait发生列表。

可以确认从等待Buffer Busy Wait的某一时刻开始变成了等待HW Enqueue。

因为Buffer Busy Waits事件和HW Enqueue事件是与FREELISTS相关,所以查看Insert对象表SUBSCRIBE的freelists,freelist groups 的属性值。

如上,SUBSCRIBE表的Freelists值设置为1。

在使用FLM(FreeList Management)管理段时,Oracle一般分配一个Master Freelist,但是在生成段的时候给Freelists值为1,Master Freelist需要兼做Process Freelist。因为只生成一个Freelist,同时会有多个进程使用同一个空闲块,而导致发生Buffer Busy Waits事件。

还有,Master Freelist会储存新的空闲块,个别的进程在需要空闲块时,从Master Freelist中获取空闲块。但是,主空闲列中没有空闲块的时候,需要获取HW锁利用HWM获得空闲块。这过程中发生HW Enqueue。

即,因为多个会话执行Insert的表Freelist属性值是1,发生了buffer lock争用,从而导致Active Session剧增。这时,将有问题的表的freelist值改为可以同时进行多个进程个数,或者考虑使用ASSM(Auto Segment Space Management)来解决问题。