x$bh视图除了提供了tch来表示一个块的热的程度,同时还可以通过这个视图观察到db buffer的另一个特点就是cr读
在
oracle数据库中db buffer中对于一个块默认情况下最多可以保留6个cr的读一致的块。buffer cache中cache的每一个block都在x$bh中表示一行,因此一个block对应的cr块最多也可以有6行,这是通过一个隐含参数来控制这个默认大小的:
_db_block_max_cr_dbaSQL> select
2 x.ksppinm name,
3 y.ksppstvl value,
4 y.ksppstdf isdefault,
5 decode(bitand(y.ksppstvf,7),1,'MODIFIED',4,'SYSTEM_MOD','FALSE') ismod,
6 decode(bitand(y.ksppstvf,2),2,'TRUE','FALSE') isadj from
7 sys.x$ksppi x,
8 sys.x$ksppcv y
9 where
10 x.inst_id=userenv('Instance') and
11 y.inst_id=userenv('Instance') and
12 x.indx=y.indx and
13 x.ksppinm like '%_&par%'
14 order by
15 translate(x.ksppinm,'_','');
输入 par 的值: db_block_max_cr_dba
原值 13: x.ksppinm like '%_&par%'
新值 13: x.ksppinm like '%_db_block_max_cr_dba%'
NAME
----------------------------------------------------------------
VALUE
-----------------------------------------------------------------------------
ISDEFAULT ISMOD ISADJ
--------- ---------- -----
_db_block_max_cr_dba
6
TRUE FALSE FALSE
下面做个实验来观察这种现象
SQL> select file_name from dba_data_files;
FILE_NAME
------------------------------------------------------------
D:\ORACLE\ORA92\ICMNLSDB\SYSTEM01.DBF
D:\ORACLE\ORA92\ICMNLSDB\UNDOTBS01.DBF
D:\ORACLE\ORA92\ICMNLSDB\INDX01.DBF
D:\ORACLE\ORA92\ICMNLSDB\TOOLS01.DBF
D:\ORACLE\ORA92\ICMNLSDB\USERS01.DBF
D:\ORACLE\ORA92\ICMNLSDB\ALAN.DBF
D:\ORACLE\ORA92\ICMNLSDB\PERFSTAT.DBF
D:\ORACLE\ORA92\ICMNLSDB\MYTEXT01.DBF
已选择8行。
SQL> create tablespace mycr
2 datafile 'D:\ORACLE\ORA92\ICMNLSDB\mycr.dbf' size 10M
3 extent management local uniform. size 64k
4 ;
表空间已创建。
SQL> create table test
2 (int number) tablespace mycr;
表已创建。
SQL> begin
2 for i in 1..5000
3 loop
4 insert into test values(i);
5 end loop;
6 end;
7 /
PL/SQL 过程已成功完成。
SQL> commit;
提交完成。
SQL> analyze table test compute statistics;
表已分析。
SQL> select file_id,extent_id,block_id,blocks,bytes from dba_extents
2 where segment_name='TEST';
FILE_ID EXTENT_ID BLOCK_ID BLOCKS BYTES
---------- ---------- ---------- ---------- ----------
7 0 9 8 65536
7 1 17 8 65536
这里block# 9表示的是段头
SQL> select num_rows,blocks,empty_blocks, num_freelist_blocks
2 from dba_tables where table_name='TEST' and wner='SYS';
NUM_ROWS BLOCKS EMPTY_BLOCKS NUM_FREELIST_BLOCKS
---------- ---------- ------------ -------------------
5000 12 3 5
SQL> select file#,block# from
2 (select dbms_rowid.rowid_relative_fno(rowid) file#,
3 dbms_rowid.rowid_block_number(rowid) block#
4 from test) group by file#,block#;
FILE# BLOCK#
---------- ----------
7 10
7 11
7 12
7 13
7 14
7 15
7 16
7 17
已选择8行。
表中的数据占用了8个block。
SQL> select data_object_id from dba_objects where wner='SYS' and object_name='TEST';
DATA_OBJECT_ID
--------------
26826
这里我们跳取block 12来实验
SQL> select file#,dbablk,tch,flag,
2 decode(bitand(flag,1),0,'N','Y') dirty,
3 decode(bitand(flag,16),0,'N','Y') temp,
4 decode(bitand(flag,1536),0,'N','Y') ping,
5 decode(bitand(flag,16384),0,'N','Y') stale,
6 decode(bitand(flag,65536),0,'N','Y') direct,
7 decode(bitand(flag,1048576),0,'N','Y') new
8 from x$bh
9 where dbablk= 12 and bj= 26826 and tch >0;
FILE# DBABLK TCH FLAG D T P S D N
---------- ---------- ---------- ---------- - - - - - -
7 12 1 35659776 N N N N N N
我们可以看一下tch目前的状态为1
下面touch一下block 12
SQL> select count(1) from test
2 where rowid = dbms_rowid.rowid_create(1,26826,7,12,0);
COUNT(1)
----------
1
三秒后:
SQL> select file#,dbablk,tch,flag,
2 decode(bitand(flag,1),0,'N','Y') dirty,
3 decode(bitand(flag,16),0,'N','Y') temp,
4 decode(bitand(flag,1536),0,'N','Y') ping,
5 decode(bitand(flag,16384),0,'N','Y') stale,
6 decode(bitand(flag,65536),0,'N','Y') direct,
7 decode(bitand(flag,1048576),0,'N','Y') new
8 from x$bh
9 where dbablk= 12 and bj= 26826 and tch >0
10 ;
FILE# DBABLK TCH FLAG D T P S D N
---------- ---------- ---------- ---------- - - - - - -
7 12 2 35659776 N N N N N N
tch确实加1,变为了2
下面开始构造CR
sess 1:
SQL> update test set int=1011 where rowid=dbms_rowid.rowid_create(1,26826,7,12,0);
已更新 1 行。
sess 2:
SQL> select * from test
2 where rowid=dbms_rowid.rowid_create(1,26826,7,12,0);
INT
----------
1321
这个时候我们看:
SQL> select file#,dbablk,tch,flag,
2 decode(bitand(flag,1),0,'N','Y') dirty,
3 decode(bitand(flag,16),0,'N','Y') temp,
4 decode(bitand(flag,1536),0,'N','Y') ping,
5 decode(bitand(flag,16384),0,'N','Y') stale,
6 decode(bitand(flag,65536),0,'N','Y') direct,
7 decode(bitand(flag,1048576),0,'N','Y') new
8 from x$bh
9 where dbablk= 12 and bj= 26826 and tch >0
10 ;
FILE# DBABLK TCH FLAG D T P S D N
---------- ---------- ---------- ---------- - - - - - -
7 12 1 524289 Y N N N N N
7 12 3 35659777 Y N N N N N
如此反复这样的操作,最终针对block# 12只有6个CR存在:
SQL> /
FILE# DBABLK TCH FLAG D T P S D N
---------- ---------- ---------- ---------- - - - - - -
7 12 1 524289 Y N N N N N
7 12 3 35659777 Y N N N N N
7 12 1 524289 Y N N N N N
7 12 1 524289 Y N N N N N
7 12 1 524289 Y N N N N N
7 12 1 524289 Y N N N N N
已选择6行。
因为默认情况下一个buffer block最多有6个对应的CR块,那么如果再有
SQL语句进行一致性访问,就不会再构造CR块,而是直接重用buffer中的CR块