Buffer Busy Waits是怎么产生的?
作为一个Oracle DBA,如果你从未遇到过Buffer Busy Waits等待,那么你算不上一个真正的Oracle Dba。
Buffer Busy Waits是Oracle 数据库非常常见的一个等待,特别是在并发写比较频繁的环境里。说起为什么会产生这个等待,首先要描述下,Oracle读写数据块的过程:
-
首先依据数据块地址计算出(Hash算法)数据块所在的Hash Bucket。
-
根据桶的编号,计算出保护这个桶的CBC Latch,然后申请CBC Latch,查找数据块在不在桶里(内存里),我们这里假设在内存里。
-
读取/修改数据块。
-
释放CBC Latch。
以上的描述看似是非常通畅,但是存在一个问题,CBC Latch的持有是排他的,如果在排他持有CBC Latch的情况下,读取数据块内容,那么这个Latch的持有时间就会比较长,因为相对于Latch的获取和释放这种CPU原子操作,读取数据块的内容是非常耗时的,因此在持有CBC Latch的情况下,读取数据块,对于读写频繁的数据库/块,那么势必会造成CBC Latch的争用。
为了解决这个问题,Oracle引入了buffer pin的功能。
我们有必要对读取数据块的内容重新做下描述,大致步骤如下:
-
首先依据数据块地址计算出(Hash算法)数据块所在的Hash Bucket。
-
然后申请CBC Latch,查找、定位到数据块
-
以S/X模式获取数据块的buffer pin。(读取获得S模式,修改获得X模式,S和S模式具有兼容性,S和X、X和X模式不具有兼容性)
-
释放CBC Latch
-
在Pin的保护下,读取/修改数据块
-
获得CBC Latch
-
释放Buffer Pin
-
释放CBC Latch
看似步骤复杂了,CBC Latch获取/释放了两次,可是却大大的提高了并发度。
上面描述的步骤里,持有CBC Latch的目的变得单纯,只是为了增加Buffer的Pin模式,然后依靠Pin的模式兼容性来保护数据块,例如:S和S模式的Pin是兼容的,可以并发的读取,S和X模式是不兼容的,后来的会话需要产生等待。
虽然Latch的持有是排他的,但是这个时间极端,引起争用的可能性不大,如果大家都是来读数据块的,那么Buffer Lock的S模式之间都是具有兼容性的,不会产生争用。但是同一个时刻,如果一个进程以S模式持有了数据块的Buffer Lock,另一个进程想以X模式持有,那么就会出现争用,因为道理很简单,S模式的Buffer Pin和X模式的Buffer Pin不兼容。
同理,两个同时欲修改同一个数据块的进程,也会遭遇Buffer Pin冲突.这个冲突以ORACLE 等待事件表示出来就是Buffer Busy Waits,也就是说Buffer Busy Waits等待的本质是buffer pin的争用导致的。
我们平时经常说读不阻塞写,写不阻塞读,那是在物理的数据块级别,在内存里,读写/写写在同一个时刻都是互相阻塞的。只有读读不阻塞。
为了方便理解,上面很多步骤做了简化,下面对某些点做些补充:
-
一旦你Pin住了一个数据块,不需要立即去UNPin(移除Pin)它。ORACLE认为你的本次调用后还有可能去访问这个数据块,因此保留了Pin,直到本次调用结束再UNPin。
-
Oracle在对唯一索引/undo块/唯一索引的回表/索引root、branch块的设计上,在访问(读取)的时候,获取的是共享的CBC Latch,不需要去Pin数据块,在持有共享CBC Latch的情况下读取数据块。可能的原因是这些块修改的可能性比较小,因此Oracle单独的采用这种机制。因此对于普通数据块的读取都是需要获取2次CBC Latch,而对于这种特殊的数据块,只获取一次共享CBC Latch就可以了。
-
我们上面所说的情况都是在数据块已经存在在内存里的情况。如果数据块不在内存,有可能会产生READ BY OTHER SESSION争用等待。
-
上面描述只符合10G后的版本。在10G前读读也会产生Buffer BUSY WAITS,10G后把这方面的Buffer BUSY WAITS归到了READ BY OTHER SESSION等待里。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22034023/viewspace-736556/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/22034023/viewspace-736556/

7261

被折叠的 条评论
为什么被折叠?



