天天看點

Oracle dirty block的一些探讨(一)

今天剛吃完骨頭煲,回到家已是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]