问题描述
数据块在物理磁盘上叫做block,读取到内存以后叫做buffer
数据库中有个X$BH表,buffer header表,这个表中的每一行数据都对应着buffer cache中的一个buffer
c##ucr_ld@TEST> create table test as select object_id,object_name from dba_objects where rownum<2; Table created. c##ucr_ld@TEST>select * from test; OBJECT_ID OBJECT_NAM ---------- ---------- 30 I_COBJ#
查看该表占用了8个数据块
c##ucr_ld@TEST>exec show_space('TEST'); Total Blocks............................8 Total Bytes.............................65536 Unused Blocks...........................4 Unused Bytes............................32768 Last Used Ext FileId....................11 Last Used Ext BlockId...................128 Last Used Block.........................4
TEST表占用了11号文件的第131号数据块
c##ucr_ld@TEST>select dbms_rowid.rowid_relative_fno(rowid) file#,dbms_rowid.rowid_block_number(rowid) block# from test; FILE# BLOCK# ---------- ---------- 11 131
其中11号文件的第130号数据块存放的是数据块的段头信息
c##ucr_ld@TEST>select header_file,header_block from dba_segments where owner='C##UCR_LD' and segment_name='TEST'; HEADER_FILE HEADER_BLOCK ----------- ------------ 11 130
TEST表的131号数据块正在被以排它模式占有
c##ucr_ld@TEST>select file#,block#,status from v$bh where file#=11 and block#=131; FILE# BLOCK# STATUS ---------- ---------- ------------------------------ 11 131 xcur
请问块有哪些状态,以及各种状态直接的变化是怎么样的
专家解答
v$bh的status状态的含义:
Oracle使用v$bh视图记录与data buffer相关的信息,该视图详细记录了数据缓冲中每一个数据块的状态信息,数据块的状态有以下几种:
sys@TEST>select distinct status from v$bh;
STATUS
------
xcur 表示该数据块处于排它模式。假设我们要读取一个数据块到buffer cache,这个被读入的数据块就叫做current块
free 表示该数据块目前没有被使用
cr 表示该数据块是一个clone的数据块,可以执行共享的只读操作。
假设会话A修改了某个数据块没有提交;会话B也需要修改这个数据块,但是由于A还没有提交,所以B不能读取到A还没提交的内容。
B只能从磁盘重新读取未修改之前的数据块到内存(如果已经被修改了,需要到undo里面去根据前印象构造一个cr块,B读取的就是这个cr块)
也就是说:会话A操作的是current块,是和原始的block对应的;会话B操作的是cr块,是临时的块。如果要修改一个数据块,只能读取current块
此时清空buffer cache,可以看到TEST表对应的数据块的状态是free
sys@TEST>alter system flush buffer_cache; System altered. c##ucr_ld@TEST>select file#,block#,status from v$bh where file#=11 and block#=131; FILE# BLOCK# STATUS ---------- ---------- ------------------------------ 11 131 free 11 131 free
对该表执行select操作,此时读取的是current数据块,状态是xcur
c##ucr_ld@TEST>select * from test; OBJECT_ID OBJECT_NAM ---------- ---------- 30 I_COBJ# c##ucr_ld@TEST>select file#,block#,status from v$bh where file#=11 and block#=131; FILE# BLOCK# STATUS ---------- ---------- ------------------------------ 11 131 free 11 131 free 11 131 xcur
对该表执行DML操作,这里有疑问的是:此时该数据块同时会有current块、cr块的状态?是否表明该数据块目前以排它模式被持有,但是其他人可以以只读模式构造cr块
c##ucr_ld@TEST>update test set object_id=1; 1 row updated. c##ucr_ld@TEST>select file#,block#,status from v$bh where file#=11 and block#=131; FILE# BLOCK# STATUS ---------- ---------- ------------------------------ 11 131 free 11 131 free 11 131 cr 11 131 xcur
总结:
对一个数据块进行DML操作,只能读取current数据块并做修改
对一个数据块进行DQL操作,如果current数据块没有未提交的操作直接读取current数据块;如果current数据块有未提交的操作,需要构造一个原始block的cr块。