下面通过实验来解答上述结论。以下测试来自测试环境,数据库极少事务变化量。
首先查看表格zhoul在数据库的存放位置,由以下查询可知zhoul表格数据存放在7号文件block号为15511的数据块中。
SQL> col file# for 999
SQL> col block# for 99999
SQL> set linesize 300
SQL> select dbms_rowid.ROWID_RELATIVE_FNO(rowid) file#,dbms_rowid.ROWID_BLOCK_NUMBER(rowid) block#,i,name from zhoul;
FILE# BLOCK# I NAME
----- ------ ---------- --------------------
7 15511 1 aaa
7 15511 2 bbb
7 15511 3 ccc
为了获得比较干净的测试环境,首先切换一个归档日志,这样可以将其他事务的变化条目排除在这个online redolog之外。
SQL> alter system switch logfile;
System altered.
SQL> select * from zhoul;
I NAME
---------- --------------------
1 uuu
2 bbb
3 ccc
在内存中修改表格zhoul数据,注意将字段i=1修改成系统最新的scn值,并进行提交。这样该数据文件头在buffer_cache存储的scn将会比10995251185389略大
但应该会比10995251185563小。
SQL> update zhoul set i=(select current_scn scn from v$database) where i=1;
1 row updated.
SQL> commit;
Commit complete.
SQL> col i for 999999999999999999
SQL> select * from zhoul;
I NAME
------------------- --------------------
10995251185389 uuu
2 bbb
3 ccc
SQL> select current_scn i from v$database;
I
-------------------
10995251185563
打开statistic跟踪,可以看到全部为8个consistent gets,也就意味着15511号还在buffer_cache中。
SQL> set autot traceonly stat
SQL> select * from zhoul;
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
8 consistent gets
0 physical reads
0 redo size
523 bytes sent via SQL*Net to client
400 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
3 rows processed
现在将buffer_cache中数据块刷出至数据文件中。
SQL> alter system flush buffer_cache;
System altered.
获得包含此事务的online redolog
SQL> set autot off
SQL> select member from v$log a,v$logfile b where a.group#=b.group# and a.status='CURRENT';
MEMBER
--------------------------------------------------------------------------------
/oradata/mcstar/redo01.log
将redo01.log dump出来,由于本文只研究数据块写出操作,固只需dump layer为23,opcode为1的change。
SQL> alter system dump logfile '/oradata/mcstar/redo01.log' layer 23 opcode 1;
System altered.
打开跟踪文件可以看到,其scn为 0x0a00.080a86ef,此值和bbed结果一致。
CHANGE #1 MEDIA RECOVERY MARKER SCN:0x0000.00000000 SEQ: 0 OP:23.1
Block Written - afn: 7 rdba: 0x01c03c97 BFT:(1024,29375639) non-BFT:(7,15511)
scn: 0x0a00.080a86ef seq: 0x03 flg:0x06
BBED> dump block 15511 offset 0 count 20
File: /oradata/mcstar/zhoul01.dbf (0)
Block: 15511 Offsets: 0 to 19 Dba:0x00000000
------------------------------------------------------------------------
06a20000 973cc001 ef860a08 000a0306 3f130000
进一步将0x0a00.080a86ef转换成10进制之后为10995251185391,此值比10995251185389略大,但小于10995251185563,也就证明了我们的猜想:
block head的scn记录的是该block改变时的scn,并非从buffer_cache时刷出的scn。
SQL> col scn for 999999999999999
SQL> select to_number('0a00080a86ef','xxxxxxxxxxxx') scn from dual;