今天剛吃完骨頭煲,回到家已是21:30分。由于昨天和今天針對Oracle dirty block做了一些測試,得到了一些結果。于是想把測試過程記錄一下,以備後忘。
Oracle dirty block指的是buffer cache中發生過變化且沒有重新整理到datafile。Oracle block在block head會記錄其發生變化時的scn,
也就是說Oracle block在buffer cache更改時也會賦予Oracle目前的scn(如果目前Oracle current scn為1000,此時block發生變化,Oracle會将1000寫入block head,這在上篇blog中也有所涉及)。
本文要探讨主要有2個方面:
1、Oracle block刷到資料檔案時,是否有做判斷?
(1)如果block在buffer cache中未發生變化,執行alter system flush buffer_cache時是否也會将此block重新整理至資料檔案?
(2)如果block在buffer cache中發生了變化(也就意味着dirty block),執行alter system flush buffer_cache是否也會将此block重新整理至資料檔案?
如果會重新整理至資料檔案,當磁盤的block scn大于buffer cache中block scn時,刷出動作是否也會進行?
(3)在rac情況下,block重新整理至資料檔案是否有差別?
2、alter system checkpoint和alter system flush buffer_cache有什麼差別?
首先探讨第一種情況:
如果block在buffer cache中未發生變化,執行alter system flush buffer_cache時是否也會将此block重新整理至資料檔案?
建立業務使用者zhoul,并建立測試表格zhoul
SQL> conn zhoul/zhoul
Connected.
SQL> create table zhoul (i int,name varchar(20));
Table created.
SQL> insert into zhoul values(1,'aaa');
1 row created.
SQL> insert into zhoul values(2,'bbb');
1 row created.
SQL> insert into zhoul values(3,'ccc');
1 row created.
SQL> commit;
Commit complete.
[color=red]執行全量checkpoint,確定變化塊寫入資料檔案。[/color]
SQL> alter system checkpoint;
System altered.
利用dbms_rowid函數擷取表格資料對應的資料檔案号和block号
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
SQL> select name from v$datafile where file#=7;
NAME
--------------------------------------------------------------------------------
/oradata/mcstar/zhoul01.dbf
以aaa列為例,将其轉化為16進制之後是616161
SQL> select dump('aaa',16) from dual;
DUMP('AAA',16)
----------------------
Typ=96 Len=3: 61,61,61
利用bbed find字元串功能,定位到行aaa在block 15511偏移量位置8185之後開始存儲,共占用3個位元組。
[[email protected] admin]$ bbed filename=/oradata/mcstar/zhoul01.dbf blocksize=8192 password=blockedit mode=edit
BBED> find /c aaa
File: /oradata/mcstar/zhoul01.dbf (0)
Block: 15511 Offsets: 8185 to 8191 Dba:0x00000000
------------------------------------------------------------------------
61616105 067757
<32 bytes per line>
将其改變為zzz字元串,注意這是利用bbed在實體級别修改,Oracle 在buffer cache中并未修改,是以Oracle依舊認為block 15511狀态為clean。
BBED> modify /c zzz
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y
File: /oradata/mcstar/zhoul01.dbf (0)
Block: 15511 Offsets: 8185 to 8191 Dba:0x00000000
------------------------------------------------------------------------
7a7a7a05 067757
<32 bytes per line>
BBED> sum apply
Check value for File 0, Block 15511:
current = 0x9976, required = 0x9976
BBED> exit
如果此時查詢zhoul業務表格,可以看到aaa依然存在,并沒有出現我們所期望的zzz列,這是因為aaa列依舊在buffer cache中。
SQL> select * from zhoul;
I NAME
---------- --------------------
1 aaa
2 bbb
3 ccc
将buffer cache刷出,再次執行,[color=red]可以看到zzz列出現[/color],也就是我們利用bbed實體上修改的結果。
SQL> alter system flush buffer_cache;
System altered.
SQL> select * from zhoul;
I NAME
---------- --------------------
1 zzz
2 bbb
3 ccc
此時檢視資料檔案,依然是7a7a7a。
BBED> dump block 15511 offset 8185
File: /oradata/mcstar/zhoul01.dbf (0)
Block: 15511 Offsets: 8185 to 8191 Dba:0x00000000
------------------------------------------------------------------------
7a7a7a05 067757
<32 bytes per line>
通過以上測試,我們可以得出以下結論:[color=red]當Oracle認為此block不是dirty block,為加快flush buffer cache效率,Oracle并不會将其真正刷至datafile中。
當執行alter system flush buffer cache時,隻會将其在記憶體中清空。[/color]