千家信息网

实例演示oracle数据块状态视图v$bh的用法一 获取oracle对象所占用的数据块

发表于:2024-09-22 作者:千家信息网编辑
千家信息网最后更新 2024年09月22日,1,创建一个测试表,test,并且插入10000行数据;SQL> create table test (id int);SQL> begin2 for i in 1..10000 loop3 inse
千家信息网最后更新 2024年09月22日实例演示oracle数据块状态视图v$bh的用法一 获取oracle对象所占用的数据块

1,创建一个测试表,test,并且插入10000行数据;
SQL> create table test (id int);

SQL> begin
2 for i in 1..10000 loop
3 insert into test values(i)
4 end loop;
5 end;
6 /

SQL> commit


2
,创建一个存储过程SHOW_SPACE

文件:

show_spaceprocedure.rar

大小:

0KB

下载:

下载

create or replace procedure show_space

( p_segname in varchar2,

p_owner in varchar2 default user,

p_type in varchar2 default 'TABLE',

p_partition in varchar2 default NULL )

as

l_total_blocks number;

l_total_bytes number;

l_unused_blocks number;

l_unused_bytes number;

l_LastUsedExtFileId number;

l_LastUsedExtBlockId number;

l_last_used_block number;

procedure p( p_label in varchar2, p_num in number )

is

begin

dbms_output.put_line( rpad(p_label,40,'.') ||

p_num );

end;

begin

dbms_space.unused_space

( segment_owner => p_owner,

segment_name => p_segname,

segment_type => p_type,

partition_name => p_partition,

total_blocks => l_total_blocks,

total_bytes => l_total_bytes,

unused_blocks => l_unused_blocks,

unused_bytes => l_unused_bytes,

last_used_extent_file_id => l_LastUsedExtFileId,

last_used_extent_block_id => l_LastUsedExtBlockId,

last_used_block => l_last_used_block );

p( 'Total Blocks', l_total_blocks );

p( 'Total Bytes', l_total_bytes );

p( 'Unused Blocks', l_unused_blocks );

p( 'Unused Bytes', l_unused_bytes );

p( 'Last Used Ext FileId', l_LastUsedExtFileId );

p( 'Last Used Ext BlockId', l_LastUsedExtBlockId );

p( 'Last Used Block', l_last_used_block );

end;

/

3,检查表test的空间使用情况:
SQL> exec show_space('TEST');
Total Blocks............................24
Total Bytes.............................196608
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................1
Last Used Ext BlockId...................62177
Last Used Block.........................5

由上可知,该表test共占用了24个数据块,196608字节,文件ID1

4
获得表test在数据块中的分布情况:
SQL> select f,b from (
2 select dbms_rowid.rowid_relative_fno(rowid) f,
3 dbms_rowid.rowid_block_number(rowid) b
4 from test) group by f,b order by b;

F B
---------- ----------
1 62162
1 62163
1 62164
1 62165
1 62166
1 62167
1 62168
1 62169
1 62170
1 62171
1 62172
1 62173
1 62174
1 62175
1 62176
1 62177

16 rows selected.
由此可见,表test中的数据共占用了16个数据块,但是前面第三步中,发现该表占用了24个数据块。这是正常的,因为oracle本身会使用8个数据块来记录段头、位图块等额外的信息。我们现在只需要了解到,表test共占用了24个数据块,其中16个是数据,8个是表信息。

5
,检查x$bhv$bh的更新:
SQL> select file#,dbablk,tch from x$bh where bj=
2 (select data_object_id from dba_objects
3 where wner='SYS' and object_name='TEST')
4 order by dbablk;

FILE# DBABLK TCH
---------- ---------- ----------
1 62161 6
1 62162 3
1 62163 3
1 62164 3
1 62165 3
1 62166 3
1 62167 3
1 62168 3
1 62169 3
1 62170 3
1 62171 3
1 62172 3
1 62173 3
1 62174 3
1 62175 3
1 62176 3
1 62177 3
1 62178 3
1 62179 3
1 62180 3
1 62181 3

21 rows selected.

SQL> select file#,block#,status from v$bh where bjd=
2 (select data_object_id from dba_objects
3 where wner='SYS' and object_name='TEST')
4 order by block#;

FILE# BLOCK# STATUS
---------- ---------- -------
1 62161 xcur
1 62162 xcur
1 62163 xcur
1 62164 xcur
1 62165 xcur
1 62166 xcur
1 62167 xcur
1 62168 xcur
1 62169 xcur
1 62170 xcur
1 62171 xcur
1 62172 xcur
1 62173 xcur
1 62174 xcur
1 62175 xcur
1 62176 xcur
1 62177 xcur
1 62178 xcur
1 62179 xcur
1 62180 xcur
1 62181 xcur

21 rows selected.

这里可以看到,在v$bhx$bh中得到的数据块,是从621616218121条记录,但是在第四步中,我们知道数据是占用了621626217716个数据库,这里,62161数据块里面存放的是段头信息,可以通过如下命令进行验证:
SQL> select header_file,header_block from dba_segments
2 where wner='SYS' and segment_name='TEST';

HEADER_FILE HEADER_BLOCK
----------- ------------
1 62161

v$bh视图中,我们可以看到这21个数据块都是xcur状态,表示这些数据块都是排斥状态,正在被使用,该字段还有其他的类型,请参见数据块的状态类型

oracle缓冲块(data block)状态类型

oracle的缓冲块的管理机制一直没有正式的发布过,因此许多有经验的oracle工程师都是通过经验或者一下oracle文档中的注释来推断oracle的缓冲块的管理机制的。

事实上,oralce使用v$bh视图来记录与数据缓冲(data buffer)相关的信息,它详细记录了数据缓冲中每一个数据块(data block)的状态信息。

v$bh视图中的status字段,记录了数据块的状态,在非OPS、非RAC这样的集群环境中,数据块的状态会是下列几种之一:xcurcrreadfree,用户可以通过如下命令得到数据库的状态信息:
SQL> select unique status from v$bh;

其状态的意义分别是:
xcur
:(exclusive current)的意思,表示该数据块处于排外模式;
cr
:表示该数据块是一个克隆(clone)的数据库,可以执行共享的只读操作;
free
:表示这是一个限制的数据块,oracle现在没有使用它;
read
:表示该数据块正在从磁盘读取数据;
write
:表示数据库正在往磁盘写入数据;

在数据库恢复过程中,该字段还有另外两个描述:mrecirec
mrec
:(media recovery)表示数据块处于介质恢复模式;
irec
:(instance recovery)表示数据块处于实例恢复模式;

RAC环境中,数据块还有另外一种模式:
scur
shared current),表示该数据库正在和其他实例共享数据。


6
,清空数据缓存:
SQL> alter system flush buffer_cache;
Oracle9i里,Oracle提供了一个内部事件,用以强制刷新Buffer Cache,其语法为:

alter session set events 'immediate trace name flush_cache level 1';

或者:

alter session set events = 'immediate trace name flush_cache';

类似的也可以使用alter system系统级设置:

alter system set events = 'immediate trace name flush_cache';

Oracle10g中,Oracle提供一个新的特性,可以通过如下命令刷新Buffer Cache:

alter system flush buffer_cache;


7
,重新检查v$bhx$bh的内容:
SQL> select file#,dbablk,tch from x$bh where bj=
2 (select data_object_id from dba_objects
3 where wner='SYS' and object_name='TEST')
4 order by dbablk;

FILE# DBABLK TCH
---------- ---------- ----------
1 62161 0
1 62162 0
1 62163 0
1 62164 0
1 62165 0
1 62166 0
1 62167 0
1 62168 0
1 62169 0
1 62170 0
1 62171 0
1 62172 0
1 62173 0
1 62174 0
1 62175 0
1 62176 0
1 62177 0
1 62178 0
1 62179 0
1 62180 0
1 62181 0

21 rows selected.

SQL> select file#,block#,status from v$bh where bjd=
2 (select data_object_id from dba_objects
3 where wner='SYS' and object_name='TEST')
4 order by block#;

FILE# BLOCK# STATUS
---------- ---------- -------
1 62161 free
1 62162 free
1 62163 free
1 62164 free
1 62165 free
1 62166 free
1 62167 free
1 62168 free
1 62169 free
1 62170 free
1 62171 free
1 62172 free
1 62173 free
1 62174 free
1 62175 free
1 62176 free
1 62177 free
1 62178 free
1 62179 free
1 62180 free
1 62181 free

21 rows selected.

这时候我们可以看到,x$bh中的tch字段,已经由原来的3变成了0,同时v$bh视图的数据块状态也变成了free,但是记录的数据块并没有发生变化,还是在62161~62181这些数据块中,这就是说,虽然数据已经被写到了磁盘中,但是数据库记录的指针并没有清空,仅仅是其状态发生了改变。

0