定义
当会话想要访问缓冲区缓存中的数据库块但由于缓冲区“繁忙”而无法访问时,会发生这种等待。 可能发生这种情况的两种主要情况是:
1. 当一个会话将数据块从磁盘读到内存中,发现内存没有空闲的内存块。
2. 发生一致性读时,由于需要创建某个时刻的前镜像,就需要在内存中申请内存块,如果没有空闲的内存块,就会发生该等待事件。
当数据库中存在热块时,即用户频繁读取或者修改某个数据块时,会发生该等待事件。
对于自身范围内产生的等待
1. 查看动态性能视图V$SESSION_WAIT涉及到的“buffer busy waits”参数
P1 = file#
P2 = block#
P3 = id
注:
file#:包含等待会话所需块的数据文件的文件号。
block#:等待会话想要访问file#中的块号。
id:官方释义如下

2. 等待时间
正常等待时间为1秒。如果会话在上次等待期间一直在等待独占缓冲区,那么它将等待3秒。会话将保持超时/等待,直到它申请到缓冲区。
3. 寻找“Blockers”
找到阻塞过程可能非常困难,因为所需的信息没有外化。如果P3显示“buffer busy waits”正在等待块读取完成,则阻塞会话可能正在等待I/O等待(例如:“db file sequential read”或“db file scattered read”)用于相同的file#和block#。
如果等待是由于缓冲区处于不兼容模式,那它应该很快被释放。
对于系统范围内产生的等待
如果等待缓冲区所非常耗时,那么最好确定哪个段正在发生争用。Bstat/estat或STATSPACK报告的“缓冲区繁忙等待统计”部分显示了哪些块类型看到最多的争用。使用以下SQL查询等待时间最多的块:
SELECT time, count, class FROM V$WAITSTAT ORDER BY time,count;
使用以下SQL查看发生等待时块的保存位置:
SELECT kcbwhdes, why0+why1+why2 "Gets", "OTHER_WAIT" FROM x$kcbsw s, x$kcbwh w WHERE s.indx=w.indx and s."OTHER_WAIT">0 ORDER BY 3;
用下面的SQL可以查看等待最多的文件,因此通过组合上述信息,我们知道哪个文件中的什么块类型导致等待:
SELECT count, file#, name FROM x$kcbfwait, v$datafile WHERE indx + 1 = file# ORDER BY count;
可以使用如下查询查看每个文件中的段:
SELECT distinct owner, segment_name, segment_type FROM dba_extents WHERE file_id= &FILE_ID;
如果列出的类型有大量段,可重复运行以下语句并收集输出,并每经过一段时间对结果进行排序以查看哪些文件和块显示争用:
SELECT p1 "File", p2 "Block", p3 "Reason" FROM v$session_wait WHERE event='buffer busy waits';
减少等待和等待时间的方法
由于该等待事件是由于对特定块的争用,所以消除块的争用的原因是最好的方式。 请注意,数据块的“buffer busy waits”通常是由于多个进程重复读取相同的块(例如:如果很多人扫描相同的索引),第一个会话快速处理缓冲区缓存中的块,然后块必须从磁盘读取。其他会话(扫描相同的索引)快速“赶上”并想要当前正在从磁盘读取的块,他们会等待缓冲区腾出空间,因为有人已经在读取该块。
对特定类型的争用可以参考以下方法来减少争用:
