语言
<< 返回文章列表

数据恢复:DUMP Block的数据读取与脏数据写入影响

2017年12月25日
张乐奕
1439

【云和恩墨,提供7*24最专业的数据恢复(Oracle,MySQL,SQL server)服务,致力于为您的数据库系统做最后一道安全防护!服务热线:010-59007017-7030】数据恢复|数据库运维|性能优化|安全保障|Oracle培训|MySQL培训


如果我们执行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则表示仍然是脏数据。