某天,客户反映其监控平台发现其一套数据库7月20日及24日在早晨7:03分和8:09分两个时间段节点1出现会话数突增情况,持续时间较短,问题时间段应用并未受到影响,客户希望帮其查找原因。
环境为11.2.0.4的双节点RAC。
通过收集的ASH信息我们可以在7月20日的07:03分和7月24日的08: 09分看到会话出现突增情况,其他时间段会话相对较平稳,问题时间点过后,会话数再次恢复平稳。
7月20日:
7 月 24 日:
在对问题时间段等待事件进行查看,该时间段内出现大量的 ”buffer busy waits” 等待事件,等待的会话并无 blocking session ,语句类型均为 INSERT , SQL_ID 均为: 8qy4f5hpsrmu4 ,而对象为 98866 ,在 7 月 24 日,问题时间段又伴有少量的 ”latch: cache buffers chains” 和大量的 ”enq: HW -contention” 。
7 月 20 日:
7 月 24 日:
对等待事件进行汇总后,等待次数排名第一位的等待事件均为 ”buffer busy waits” ,如下:
7 月 20 日
7 月 24 日
通过上面的信息在表象中看到是由于系统中大量并发 INSERT 语句同时向 98866 对象插入数据,而引起的会话数突增,且会话均等待 ”buffer busy waits” 。
那系统中为何同时出现大量 INSERT 语句的会话?该时间点内应用确实发出如此多的 INSERT 语句?而又同时向相同的对象中插入数据产生的 ”buffer busy waits” ?还是由于 ”buffer busy waits” 而引起的大量会话出现阻塞?
根据应用反馈,系统中的数据插入较平稳,问题时间段业务量并未发生变化,这样可以排除第一种可能性。
先看何为 ”buffer busy waits” , “buffer busy waits” 等待事件的发生情况为当会话以独占模式持有 buffer pin 锁时,其他会话以非兼容模式申请 buffer pin 锁,此时申请 buffer pin 锁的会话产生的等待事件为 buffer busy waits 。 引起系统 ”bufferbusy wiats” 的原因很多,常见的情况有如下情况:
1. 大量的并发 DML 语句,修改相同的数据块
2. DML 语句慢,导致以排他模式持有 bufferpin 时间过长( DML 语句慢的原因可能由于系统 redo 量过高或者 lgwr 慢等原因导致)
另外,通过对等待事件所发生位置进行统计发现 ”buffer busy waits” 均发生在少数的数据块中。
7 月 20 日
7 月 24 日
大量的会话又为何向同一个数据块中插入数据?通过对发生大量 ”buffer busy waits” 的数据块进行 dump ,有如下发现 :
218/4161664
19/8250
其中 218/4161664 为 L1 , 19/8250 为段头, L1 与段头居然出现了大量的 ”buffer busy waits” ,如果对数据插入时的机制有所了解,问题原因其实已经展现出来,在使用 ASSM 的段空间管理方式下,正常插入语句在向段中插入数据时,将会根据会话的 pid 信息计算 hash 值 n ,根据计算结果在 L3/L2 中选择第 n 个 L1 ,这里需要注意插入时所选择的 L1 是在高水位线之下的 L1 ,在根据 pid 计算 hash 值将数据插入到 L1 中的第 n 个数据块里,会话不同,插入的数据将分散到不同的块中,当 L1 中指向的数据块使用率出现变化 (25% 50% 75% FULL) 时将会修改 L1 中对该数据块空间使用情况标记位的修改,因其为修改,将以独占模式持有 L1 段头的 buffer pin 锁,在问题时间段内同时伴有大量的高水位推进 ”enq: HW - contention” 等待事件,段的高水位线记录在段头,这样也解释了为什么段头会出现大量的 ”buffer busy waits” ,其实根据上面的信息基本可以分析出是由于系统中持续插入数据,由于高水位线低 ( 高水位线的推进是以 L1 中指向的块的数量进行推进 ) ,大量的数据插入时聚集在高水位线下 L1 中指向的数据块,而引起大量的“ buffer busy waits ”,导致会话突增,这种问题较少见,如果需要避免该问题,可以采用手工推高高水位的方式,这样可选择的 L1 数量,数据块的数量也随着增多,避免插入的数据块过于集中。
| 作者简介