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事件的发生。
buffer busy wats等待事件的等待参数如下。
P1:File#
P2:Block#
p3:在Oracle 10g表示的是块类(block class),在Oracle 9i表示的是Reason Code。
一般等待1秒。假如为了以独占模式获取Buffer Lock等待Buffer busy wait事件1秒后,再次获取时需要等待3秒。要读取特定块的会话必须获得Buffer Lock。
因不同的块类而发生buffer busy waits事件的原因和解决方法如下。
数据块(块类=1)
用户应用程序的多个会话对同一块执行修改的时,一般称这种块为热块(Hot Block)。解决热块的方法有以下几种。对用户应用程序进行修改:通过对应用修改使得多个会话不会同时对一个块进行修改。
段头(段类=4)
使用FLM的时候,在Storage属性中设置充分大的FREELISTS属性值。如果是在OPS或RAC的环境下,需要给FREELIST GROUPS设置跟实例个数一样的值。设置了FREELIST GROUPS属性值后,与段头块使用不同的FREELIST,所以会减少对段头块的争用。
位图(Bitmap)块(块类=8,9,10)
使用ASSM(Automatic Segment Space Management)时可能会发生三个阶段的位图块的争用。位图块中发生的块争用无法利用Oracle的调优而改善,而是要通过应用程序的修改, 减少过多的并发的DML。
ASSM中大规模的同时DML相比较FLM是会有更多一点的开销。但大部分情况下的这种开销是可以无视的。ASSM相比FLM提供更多优点,特别对RAC提供最佳性能。
回滚头块(块类=15+2*r)
使用AUM(Automatic Undo Management)的时候在回滚头的块不会经常出现发生争用。使用手动模式的回滚段时,提供足量的回滚段数而减少回滚段的争用。
下图是通过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秒。
因为在Oracle9i版本中Buffer Busy Wait(id130)事件在10g版本上更名为Read By Other Session,所以变成Read by other session的分析案例。
需要分析的实例是发生了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)来解决问题。