从LRUW写和从检查点队列写区别是什么呢?为什么这种紧急情况写,就要从LRUW写呢?
回答这个问题,主要要看写完的脏块会如何处理。
如果脏块从检查点队列中写到磁盘,脏块在LRU、LRUW链表的位置,不会任何变化,这一点很容易证明:

SQL> select dbms_rowid.ROWID_RELATIVE_FNO(rowid),dbms_rowid.rowid_block_number(rowid),id1,id2 from a2_70m where id1<=1;

DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)        ID1        ID2
------------------------------------ ------------------------------------ ---------- ----------
                                   4                                   20          1         10
我从A2_70M选择一行,它在4号文件20号块。
然后用如下语句观察x$bh中它的状态:
set pagesize 50000
set linesize 10000
select file#,dbablk,tch,lru_flag,ba,decode(state,0,'free',1,'xcur',2,'scur',3,'cr', 4,'read',5,'mrec',6,'irec',7,'write',8,'pi',
9,'memory',10,'mwrite',11,'donated'),
decode(bitand(flag,1), 0, 'N', 'Y') dirty,US_NXT,US_PRV,LRU_FLAG from x$bh a where file#=4 and dbablk=20
order by      FILE#  ,   DBABLK;
结果如下:
     FILE#     DBABLK        TCH   LRU_FLAG BA       DECODE( D US_NXT   US_PRV   LRU_FLAG
---------- ---------- ---------- ---------- -------- ------- - -------- -------- --------
         4         20          2          0 80AEA000 xcur    N 80BF6694 80BF6694        0
从Dirty列可以看到,它并不是一个脏块。下面修改它:
SQL> update a2_70m set id2=id2+0 where id1=1;
1 row updated.
再次查看:
22:28:54 SQL> /
     FILE#     DBABLK        TCH   LRU_FLAG BA       DECODE( D US_NXT   US_PRV   LRU_FLAG
---------- ---------- ---------- ---------- -------- ------- - -------- -------- --------
         4         20          2          0 80AEA000 xcur    Y 80BF6694 80BF6694        0
已经是个脏块了。LRU_FLAG为0,说明它在主LRU上。这是因为ID1列上有索引,更新产生的读操作,是非全表扫描,所以它被放在主LRU上。全
表扫描的块,将被保留在辅助LRU中。
将增量检查点改的频繁些:
SQL> alter system set log_checkpoint_timeout=5;
System altered.
5秒一次,很快的,4号文件20号块已经不是脏块了,这是观察结果:
22:31:18 SQL> /
     FILE#     DBABLK        TCH   LRU_FLAG BA       DECODE( D US_NXT   US_PRV   LRU_FLAG
---------- ---------- ---------- ---------- -------- ------- - -------- -------- --------
         4         20          2          0 80AEA000 xcur    N 80BF6694 80BF6694        0
虽然不是脏块了,但它的LRU_FLAG列值,US_NXT、US_PRV列值,都没有变化。
这说明脏块虽然被写到磁盘中了,但它在Buffer Cache众链表中的位置,没有变化。

再来看看从LRUW中写出的情况,将log_checkpoint_timeout重新改回很大的值:
SQL> alter system set log_checkpoint_timeout=100000;
System altered.
再次修改4号文件20号块:
SQL> update a2_70m set id2=id2+0 where id1=1;
1 row updated.
确认它已经是脏块了:
22:43:39 SQL> /
     FILE#     DBABLK        TCH   LRU_FLAG BA       DECODE( D US_NXT   US_PRV   LRU_FLAG
---------- ---------- ---------- ---------- -------- ------- - -------- -------- --------
         4         20          1          0 80AEA000 xcur    Y 80BF6694 80BF6694        0
下面将a4_70m改为CACHE。目的是让它可以进入主LRU:
SQL> alter table lhb.a4_70m cache;
Table altered.
全扫描一个a4_70m:
select count(*) from a4_70m;

再来观察4号文件20号块:
22:51:21 SQL> /
     FILE#     DBABLK        TCH   LRU_FLAG BA       DECODE( D US_NXT   US_PRV   LRU_FLAG
---------- ---------- ---------- ---------- -------- ------- - -------- -------- --------
         4         20          1          4 7B72E000 xcur    N 7B7F7E7C 7B7F7E7C        4
已经不是脏块了,但它的LRU_FLAG列值为4,说明它已经被移到辅助LRU中了。并且,它的US_NXT、US_PRV列指针也都变化了。
这就是从检查点队列和从LRUW写脏块的最大区别,从检查点队列写完脏块,脏块只是变的不脏了,其他没有任何变化。但从LRUW写完脏块,块
要被放入辅助LRU,这样,块将会被很快覆盖掉。
Oracle之所设计两种写脏块模式,就是为了应对脏块较多的紧急情况。此时如果还从检查点队列写,辅助LRU中的块数量不会增加,前台进程还
是无法快速找到可用块。如果从LRUW写,写完的块被放入辅助LRU,只要这些脏块的TCH值不超过2,它们马上就可以被其他进程重用。
好了,关于LRUW,还有一个问题,我刚才的实验,update a2_70m set id2=id2+0 where id1=1; ,这条语句,会将块放在主LRU中,如果块在
辅助LRU中,又会怎样呢?下面来测试下:
先全扫描a2_70m:
SQL> select * from a2_70m;
此时查看4号文件20号块:
22:56:11 SQL> /
     FILE#     DBABLK        TCH   LRU_FLAG BA       DECODE( D US_NXT   US_PRV   WA_NXT   WA_PRV     LRU_FLAG
---------- ---------- ---------- ---------- -------- ------- - -------- -------- -------- -------- ----------
         4         20          1          4 7C6C2000 xcur    N 7C7F5884 7C7F5884 7C7F588C 7C7F588C          4
LRU_FLAG为4,代表它在辅助LRU中,因为还没有修改,所以它不是一个脏块。
执行Update:
SQL> update a2_70m set id2=id2+0 where id1=1;
1 row updated.
再查看4号文件20号块的状态:
22:56:12 SQL> /
     FILE#     DBABLK        TCH   LRU_FLAG BA       DECODE( D US_NXT   US_PRV   WA_NXT   WA_PRV     LRU_FLAG
---------- ---------- ---------- ---------- -------- ------- - -------- -------- -------- -------- ----------
         4         20          2          4 7C6C2000 xcur    Y 7C7F5884 7C7F5884 7C7F588C 7C7F588C          4
已经是脏块了,但LRU_FLAG仍为4,仍在辅助LRU中。
好,已经达到我们的目的,在辅助LRU中制造一个脏块。
下面全扫描a3_70m,在辅助LRU中占用大量块。4号文件20号块会被覆盖吗:
22:56:28 SQL> /
     FILE#     DBABLK        TCH   LRU_FLAG BA       DECODE( D US_NXT   US_PRV   WA_NXT   WA_PRV     LRU_FLAG
---------- ---------- ---------- ---------- -------- ------- - -------- -------- -------- -------- ----------
         4         20          0          8 7C6C2000 xcur    Y 7C7F5884 7C7F5884 7C7F588C 7C7F588C          8
没有被覆盖,LRU_FLAG状态为8,说明已经移到主LRU热端了。这是因为它的TCH值大于、等于2。但它仍是脏块。

信息来源:http://www.cuug.com