在某些情况下需要手工将Data Buffer Cache写出到数据文件,例如为防止Buffer Cache中的数据对SQL执行性能的影响,为公平起见需要先对缓冲区中的数据清理。
在Oracle的不同版本里清理Buffer Cache的方法也略有不同,总体方向是向着简单快捷方向发展的。

1.Oracle 9i方法(10g中依然可用)
1)可以使用“immediate trace name flush_cache”事件强制将Buffer Cache中的数据全部写出到数据文件。
sec@ora10g> alter session set events='immediate trace name flush_cache';

Session altered.

2)当执行完上述刷新操作之后,Oracle会在alert日志留下它的“脚印”。
Tue Dec 22 21:15:10 2009
ALTER SYSTEM: Flushing buffer cache

3)使用“alter system”语句同样可以完成这个任务
sec@ora10g> alter system set events = 'immediate trace name flush_cache';

System altered.

4)看一下alert中的“脚印”,注意与“alter session”的区别,这里记录的信息更加详细,包含了“OS Pid”信息。
Tue Dec 22 21:25:29 2009
ALTER SYSTEM: Flushing buffer cache
OS Pid: 17538 executed alter system set events 'immediate trace name flush_cache'

2.Oracle 10g中为简化这个过程,提供了一个“flush buffer_cache”方法
1)具体方法
sec@ora10g> alter system flush buffer_cache;

System altered.

2)在alert中与之对应的信息如下
Tue Dec 22 21:27:03 2009
ALTER SYSTEM: Flushing buffer cache

3.演示一下在Buffer Cache写出前后对同一SQL的影响
1)全新SQL语句执行后的统计信息如下
sec@ora10g> set timing on
sec@ora10g> set autot trace statistic;
sec@ora10g> select count(*) from t;

Elapsed: 00:00:00.08

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       2102  consistent gets
       2093  physical reads
          0  redo size
        515  bytes sent via SQL*Net to client
        492  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

可见“physical reads”是2093,说明Oracle将所需的数据文件从外存读入到了Buffer Cache。

2)同样的SQL语句再次执行,此时Buffer Cache并未刷出到外存。
sec@ora10g> select count(*) from t;

Elapsed: 00:00:00.06

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       2102  consistent gets
          0  physical reads
          0  redo size
        515  bytes sent via SQL*Net to client
        492  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

此时“physical reads”物理读已为零,无需重新从外存读入数据,随之执行时间也减少了。

3)将Buffer Cache刷出后再次尝试同样的SQL
sec@ora10g> alter system flush buffer_cache;

System altered.

Elapsed: 00:00:00.15
sec@ora10g> select count(*) from t;

Elapsed: 00:00:00.08

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       2102  consistent gets
       2093  physical reads
          0  redo size
        515  bytes sent via SQL*Net to client
        492  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

因为Buffer Cache中数据已经被刷出到外存,同样的SQL的物理读情况恢复到了第一次执行时的值2093。

4.小结
当Buffer Cache包含大量数据时,刷新时间将会很长,没有“特殊需求”请不要使用这个方法。
该方法在进行SQL性能测试时教为常用,为排除Buffer Cache对于测试结果影响时可以考虑使用该方法强制Oracle重新执行物理读。

Good luck.

secooler
09.12.22

-- The End --