天天看点

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]