1. 程式人生 > 其它 >深入核心:DUMP Block的資料讀取與髒資料寫入影響

深入核心:DUMP Block的資料讀取與髒資料寫入影響

張樂奕

雲和恩墨副總經理 Oracle ACE 總監

ITPUB Oracle資料庫管理版版主、Oracle高可用版版主、ACOUG聯合創始人

如果我們執行alter system dump datafile # block #的話Oracle是否會先把block讀入到buffer cache中呢?

簡略說一下測試步驟,雖然簡單,但還是需要你深入理解Oracle的內部原理。

1。重啟一下資料庫,這樣buffer cache中幾乎就沒什麼使用者資料了,方便測試

2。隨便找一張表看看是在哪個file哪個block裡面

SQL> select header_file,header_block
  2  from dba_segments
  3  where segment_name='T1';
 
HEADER_FILE HEADER_BLOCK
----------- ------------
          4           19

3。T1表在資料檔案4中,第一個block是19,檢查v$bh,看看這個block有沒有在buffer cache中

SQL> select count(*)
  2  from v$bh
  3  where file# = 4 and block# = 19;
 
  COUNT(*)
----------
         0

4。目前buffer cache中沒有這個block,作一次dump再看看有沒有

SQL> alter system dump datafile 4 block 19;
System altered
 
SQL> select count(*)
  2  from v$bh
  3  where file# = 4 and block# = 19;
 
  COUNT(*)
----------
         0

5。至此驗證了作block dump不會把資料塊先讀入buffer cache,好,繼續作一次select看看,這次一定是讀進buffer cache了

SQL> select * from ops$kamus.t1;
         N
----------
 
SQL> select count(*)
  2  from v$bh
  3  where file# = 4 and block# = 19;
 
  COUNT(*)
----------
         1

小知識:

1. v$bh檢視儲存著buffer cache中每一個block的資訊。 2. dba_segments檢視中一個ASSM型別segment的header_block是從它的PAGETABLE SEGMENT HEADER算起的,並不包括前面用於控制free block的兩個點陣圖塊(FIRST LEVEL BITMAP BLOCK和SECOND LEVEL BITMAP BLOCK)。

進一步的:dump block會否讓剛插入的塊寫入資料檔案呢?

先放出結論:Dump Block不會引起buffer cache中的髒資料回寫入磁碟。然後是驗證的詳細步驟。

1。建立一個測試表

SQL> CREATE TABLE t (n NUMBER);
TABLE created

2。插入一條資料,提交,然後強制checkpoint

SQL> INSERT INTO t VALUES(1);
1 ROW inserted
 
SQL> commit;
Commit complete
 
SQL> ALTER system checkpoint;
System altered

3。此時這條資料一定已經寫回磁碟,這個無需驗證了,我們繼續插入另外一條資料,提交,但是不checkpoint

SQL> INSERT INTO t VALUES(2);
 
1 ROW inserted
 
SQL> commit;
 
Commit complete

4。此時這條髒資料在buffer cache中,我們可以通過dump block來驗證

block_row_dump:
tab 0, row 0, @0x1f9a
tl: 6 fb: --H-FL-- lb: 0x1  cc: 1
col  0: [ 2]  c1 02
tab 0, row 1, @0x1f94
tl: 6 fb: --H-FL-- lb: 0x2  cc: 1
col  0: [ 2]  c1 03
end_of_block_dump

5。通過dbms_rowid包取得T表中所有記錄所儲存的資料檔案號和block號,本例中取得是file#=58, block#=570

6。關鍵步驟到了,現在我們要用bbed來獲取磁碟上的資料塊內容,然後跟dump block的結果比較一下

建立一個filelist檔案,命名為files.lst。

$ cat files.lst
58 /fin/u06/cnctest2data/system12.dbf 1048576000

建立一個引數檔案par.bbd,用以被bbed呼叫

$ cat par.bbd
blocksize=8192
listfile=/home/oraaux/files.lst
mode=browse

執行bbed

$ bbed parfile=par.bbd
Password: 
 
BBED: Release 2.0.0.0.0 - Limited Production on Mon Mar 13 17:35:32 2006
Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.
************* !!! For Oracle Internal Use only !!! ***************
 
BBED> set dba 58,570
        DBA             0x0e80023a (243270202 58,570)
 
BBED> x /*rn rowdata
rowdata[0]                                  @8182    
----------
flag@8182: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8183: 0x01
cols@8184:    1
 
col    0[2] @8185: 1  --只有一條記錄,值是1
 
tailchk                                     @8188    
-------
BBED-00210: no row at this offset

到目前為止我們已經驗證了dump block並不會把髒資料寫回磁碟,為了看一下checkpoint的效果,我們繼續往下作。

7。作checkpoint

SQL> ALTER system checkpoint;
 
System altered

8。再次執行bbed

$ bbed parfile=par.bbd
Password: 
 
BBED: Release 2.0.0.0.0 - Limited Production on Mon Mar 13 17:35:32 2006
Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.
************* !!! For Oracle Internal Use only !!! ***************
 
BBED> set dba 58,570
        DBA             0x0e80023a (243270202 58,570)
 
BBED> x /*rn rowdata
rowdata[0]                                  @8176    
----------
flag@8176: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8177: 0x02
cols@8178:    1
 
col    0[2] @8179: 2  --這是後來插入的記錄,值是2
 
rowdata[6]                                  @8182    
----------
flag@8182: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8183: 0x01
cols@8184:    1
 
col    0[2] @8185: 1  --這是第一條記錄,值是1
 
tailchk                                     @8188    
-------
BBED-00210: no row at this offset

checkpoint將buffer cache中的髒資料寫回資料檔案了。

如果你覺得這個過程太複雜了,當然還有更簡單的方法,仍然是v$bh檢視,檢視v$bh.dirty欄位,如果為N表示已經被寫入磁碟,如果為Y則表示仍然是髒資料。