Free buffer waits顾名思义就是data buffer里没有空闲可用buffer,使得当前会话当前进程处于Free buffer wiats等待事件。而oracle这时在做的是DBWR写脏块,清理buffer.
为什么会产生这个等待事件?很直接的一个反应是data buffer不够大。这是可能原因之一:
原因还有其它如:
1.DBWn进程写速度不够快,或触发不够勤快,或有没有使用足够DBWn进程。
2.系统本身I/O速度比较慢。
3.延迟块清除。
4.SQL语句太滥。
这么多原因如何判断具体是那个原因导致这个等待事件?
如果Buffer cache size不够大。
有可能所有buffer都在使用中,且没有dirty buffer可写。(这个情况表时你的buffer也太小了。)
还有可能有dirty buffer可写,但是频繁从把dirty buffer写到磁盘上,导致大量物理读,和比较低的缓存命中率。
还有一种可能是系统有dirty buffer可写,但没I/O速度慢或DBWR来不及,有很多该写但末写的dirty buffer堵在cache buffer里,导致了freebuffer waits事件。
由于现在buffer越来越大,所以Oracle把一个大buffer分几个工作集。每一个工作集有各自的LRU LRUW list.DBWR进程个数由DB_WRITER_PROCESSES 参数确定。然后oracle把DBWR进程分给几个工作集使用。如果你有一个很大buffer,有几个工作集,系统又比较繁忙,(写操作量也比较大)但只有一个DBWR,那明显DBWR数量不够。
跟DBWR相关的还有一种办法增强ckpt触发的频率,但这样会有一个弊处就是会占比较多I/O资源。There is no such thing as free lunch!
延迟块清除
在事务提交前, 这个事务修改的块已被DBWR写到disk中去了,当后来这个事务提交时,oracle不可能再把它读到buffer里,把块标志为提交,只能等到下回再用到它时,到undo段里查询事务记录后,并修改块标志为已提交。
当某表有大量延迟块清除块,而后继事务想要对这个表进行全表扫描时,就会占用大量Buffers.
解决办法:
找到原因,对症下药。可以有以下方法:
A.加大Buffer Size.
alter system set buffer_cache_size=1000M;
B.增加DBWR数目.
修改DB_WRITER_PROCESSES参数设置。
C.增大ckpt触发频率.