Oracle buffer状态深入剖析

来源:这里教程网 时间:2026-03-03 17:30:29 作者:

Oracle buffer状态深入剖析

oracle学习笔记 buffer状态深入剖析

这节课把buffercache里面的 buffer的几个状态给大家讲一下 以对buffer有更深的了解

dbf的 数据块在物理磁盘上叫block 内存里面都叫buffer 一)x$bh表 数据库中有个表x$bh翻译为buffer header表这个表里面每一行数据都对应着buffercache里的一个buffer 也就是每一个在buffercache的块在x$bh里面都有一个行和它对应所以我们研究buffercache就研究x$bh就可以 先看一下这个表有多少列开始老师输出数据的格式未设置好,结果有些乱所以要设置sql语法语句数据输出格式在sqlplus命令行环境提供了很多额外的非sql语法命令其中有column 这里老师输入了column name format a10命令是sqlplus命令行格式化输出的常用命令之一执行后只在执行了它的会话中生效 column主要格式化列的显示形式用这个命令可以更改select语句中指定列的输出宽度、改变缺省的列标题、设置列标题的对齐方式等一些输出格式上面语句将在select语句中列字段name输出时的格式设置为文字型,且占10个字符宽度如果输出超出10个字符此列会多行显示,但仍然是每行10个字符是为了使结果输出工整,如果输出结果可看,这个命令可以不用此命令执行后,以后的执行的每个select语句,只要输出中有name字段,name字段的显示都是10个字符宽度 但column对desc语句的输出没有作用因为desc和column同样都不属于sql语法,是sqlplus命令行的命令column的作用范围是sql语法内的输出结果 所以老师使用了前面讲过的sqlplus的另一个格式化命令set linesize使结果有序它对在sqlplus中执行的所有命令都有效 SQL> desc x$bh Name                                      Null?    Type ----------------------------------------- -------- ---------------------------- ADDR                                               RAW(4) INDX                                               NUMBER INST_ID                                            NUMBER HLADDR                                             RAW(4) BLSIZ                                              NUMBER NXT_HASH                                           RAW(4) PRV_HASH                                           RAW(4) NXT_REPL                                           RAW(4) PRV_REPL                                           RAW(4) FLAG                                               NUMBER RFLAG                                              NUMBER SFLAG                                              NUMBER LRU_FLAG                                           NUMBER TS#                                                NUMBER FILE#                                              NUMBER DBARFIL                                            NUMBER DBABLK                                             NUMBER CLASS                                              NUMBER STATE                                              NUMBER MODE_HELD                                          NUMBER CHANGES                                            NUMBER CSTATE                                             NUMBER LE_ADDR                                            RAW(4) DIRTY_QUEUE                                        NUMBER SET_DS                                             RAW(4) OBJ                                                NUMBER BA                                                 RAW(4) CR_SCN_BAS                                         NUMBER CR_SCN_WRP                                         NUMBER CR_XID_USN                                         NUMBER CR_XID_SLT                                         NUMBER CR_XID_SQN                                         NUMBER CR_UBA_FIL                                         NUMBER CR_UBA_BLK                                         NUMBER CR_UBA_SEQ                                         NUMBER CR_UBA_REC                                         NUMBER CR_SFL                                             NUMBER CR_CLS_BAS                                         NUMBER CR_CLS_WRP                                         NUMBER LRBA_SEQ                                           NUMBER LRBA_BNO                                           NUMBER HSCN_BAS                                           NUMBER HSCN_WRP                                           NUMBER HSUB_SCN                                           NUMBER US_NXT                                             RAW(4) US_PRV                                             RAW(4) WA_NXT                                             RAW(4) WA_PRV                                             RAW(4) TCH                                                NUMBER TIM                                                NUMBER 这个表中有很多列,不可能一次研究完有些列需要重点关注如TCH、FLAG、RFLAG、HLADDR这里我们看STATE列 二)buffer的状态 在x$bh表中STATE列它应该是有8种值 摘自老师教案:state: 0, FREE, no valid block image1, XCUR, a current mode block, exclusive to this instance2, SCUR, a current mode block, shared with other instances3, CR, a consistent read (stale) block image4, READ, buffer is reserved for a block being read from disk5, MREC, a block in media recovery mode6, IREC, a block in instance (crash) recovery mode 对它的翻译是:FREE(0)=还没有使用过的块;XCURRENT(1)=实例以排他方式获取的当前模式数据块,正在被当前的instance独占SCURRENT(2)=可以与其他实例共享的当前模式数据块,正在被当前的instance共享CR(3)=作为一致性读镜像的数据块,永远不会被写入磁盘;READING(4)=正在从磁盘读出的数据块;MRECOVERY(5)=正在进行介质恢复的数据块;IRECOVERY(6)=正在进行实例恢复的数据块。 我们简单select一下SQL> select distinct state from x$bh;      STATE----------         1         3         0说面目前这个表中state只有0 1 3这三个值只用到了三个值说明现在数据库中的buffer只有这三个状态 1)free state 0号状态是FREE对某个buffer来讲它从来没有被用过、还没有和block对应就是free 2)current state和cr state XCUR SCUR CR三个理解有一定的难度1号状态是XCUR 假设现在要读一个block这个块在buffercache里面没有就把它读到buffer中去计算以后把它放到一个buffer里面这个在buffercache中的buffer就叫CUR:current块,叫当前块一个block读进一个buffer就叫current块 current块和cr(consistent read读一致性)块是有对应的 有一个a会话连接上以后对buffer块里的某个行进行修改修改完了以后没有提交这时候b会话上来以后读这个buffer块这时b想要读这个块这个块又被a修改了但是还没有提交b不能读到a没有提交的修改b就会在另外一个位置申请一个buffer块然后把这个块里面没有修改的写到新申请块已经修改的它把修改前的值在undo里面找到写入新块,构造出一个cr块然后b就读cr块这就是cr块 但是这个cr块和原始block没有对应关系b构造这个块以后把数据读出来了读出来以后这个块马上就没用了cr块马上就没有意义了 会话a操作的块是current块它永远和原始block块是对应的,无论是修改前后此buffer干净状态和脏状态都是current块cr块是会话b要读这个块但这个块不能直接读就构造一个cr块这个cr块是临时的读完以后这个块马上就没有意义了马上就可以被覆盖了 我们修改一个块只能修改current块 总结1、我们要对一个块进行增删改无论在这个块里面增加行、删除行还是要修改行我们只能修改current块只能对current块进行处理2、读的时候current块里面没有未提交的操作直接读current就可以了current里有未提交的,在其它会话中我们只能构造一个cr块 3)XCUR state和SCUR state 这地方有人理解有误,在网上各种各样的写法都有 current状态还分XCUR和SCURX是exclusive(独占的)的缩写S是shared(共享的)的缩写 我们讲过一个数据库一般都有一个实例但是也有一个数据库对应多个实例 一个数据库对应一个实例的情况下也就是在非RAC的环境下current永远都用XCUR也就是只有XCUR因为这个buffer块被这个实例独占 如果在存在RAC的环境里面才有可能出现SCURRAC中有Cache Fusion(融合)即内存融合技术也叫PCM:Parallel Cache Management并发内存管理SCUR在Cache Fusion技术机制会用到因为它需要和其它进程分享这个buffer块 在单实例环境里面current只有一种情况就是XCURSCUR在非RAC环境下是没有的 4)read state 也是数据块的一个状态 block要读到内存里的buffer里面去读的过程中要发生物理io物理io需要花费时间把block块读到buffer里面去如读了10ms这个buffer在这个10ms里面就处于一个read状态 read state就是block正在把数据写入到buffer里面去 5)MREC state,IREC state 这里M是media(介质)I是instance(实例)REC是recovery(恢复) MREC是介质恢复IREC是实例恢复 在oracle的备份恢复中才能用到在正常的数据库启动过程中或数据库使用过程中一般不会出现MREC state和IREC state的情况 状态号0、1、2、3、4出现的情况比较多 6)第8种状态write state 就是写状态 块脏了时间长了以后DBWn进程会把它写到磁盘上把它向磁盘写的过程,状态就是wirte和读是对应的 对我们来讲最经常运行的状态是读写再就是free、xcur和cr这几种状态 这就是与block对应的buffer的几种状态 三)查询块状态的例子 举一个例子现在有个表t2SQL> select * from t2;         ID NAME---------- --------------------         1 xkj         2 jiagulun t2现在有两个数据行 然后SQL> alter system flush buffer_cache; System altered. 这是将整个buffercache全部清空这样可以清楚的看到sql语句生成的buffer的个数和状态但这在生产中是比较危险的因为你全部清空以后接着会发生大量的物理io 使用下面语句selecto.object_name,decode(state,0,'free',1,'xcur',2,'scur',3,'cr', 4,'read',5,'mrec',6,'irec',7,'write',8,'pi') state,count(*) blocksfrom x$bh b, dba_objects owhere b.obj = o.data_object_idand o.object_name = 'T2'group by o.object_name, stateorder by blocks desc;能查一个对象所占用buffer的情况 我们查t2表SQL> selecto.object_name,decode(state,0,'free',1,'xcur',2,'scur',3,'cr', 4,'read',5,'mrec',  2    3    4  6,'irec',7,'write',8,'pi') state,  5  count(*) blocks  6  from x$bh b, dba_objects o  7  where b.obj = o.data_object_id  8  and o.object_name = 'T2'  9  group by o.object_name, state 10  order by blocks desc; OBJECT_NAME----------------------------------------------------------------------------------------------------STATE     BLOCKS----- ----------T2free           2 目前t2虽然占了2个块但是这2个状态是free这种占用的块是free的状态很可能和刚清空了buffer_cache有关也就是t2根本没有占用buffer 这种情况是一个buffer被清空了但这个链的地方还挂着一个头指向它即使这时buffer的状态是free state这是它在清空的过程中不太彻底的一个表现 现在我们再来读一下这个表SQL> select * from t2;         ID NAME---------- --------------------         1 xkj         2 jiagulun 就读t2这个表了只是读 再执行一下SQL> selecto.object_name,  2    3  decode(state,0,'free',1,'xcur',2,'scur',3,'cr', 4,'read',5,'mrec',  4  6,'irec',7,'write',8,'pi') state,  5  count(*) blocks  6  from x$bh b, dba_objects o  7  where b.obj = o.data_object_id  8  and o.object_name = 'T2'  9  group by o.object_name, state 10  order by blocks desc; OBJECT_NAME----------------------------------------------------------------------------------------------------STATE     BLOCKS----- ----------T2xcur           2 T2free           2 结果中t2占了两个块是xcur对这个块读的话也是xcurfree的两个块不是真实的它并没有占用 执行语句:SQL> update t2 set name='jiagulunoracle' where id=1; 1 row updated.对表进行更新 另外再启一个会话 执行SQL> select * from t2;         ID NAME---------- --------------------         1 xkj         2 jiagulun这时应该产生cr块了应该会产生 在查一下t2表块的状态SQL> selecto.object_name,  2    3  decode(state,0,'free',1,'xcur',2,'scur',3,'cr', 4,'read',5,'mrec',  4  6,'irec',7,'write',8,'pi') state,  5  count(*) blocks  6  from x$bh b, dba_objects owhere b.obj = o.data_object_id  7    8  and o.object_name = 'T2'group by o.object_name, state  9   10  order by blocks desc; OBJECT_NAME----------------------------------------------------------------------------------------------------STATE     BLOCKS----- ----------T2xcur           2 T2cr             2 T2free           1产生了两个cr块在两个会话中查询结果都一样 然后在会话2中多次执行select * from t2;每次执行后立即查询t2表的块的状态可以看到这时对应的cr块会有增加,但此数值没有无限制的增加,用上面方法试验了多个不同表发现每个表对应的cr块最多只增加到5说明cr块在数据读出来以后马上就失效了,再次查询还要构造新的cr块。在查询过程中对应cr状态块没有减少,只是说明系统还没有回收。构造的cr块有上限值,说明oracle系统对它有限制 db buffer中对于一个block块默认情况下最多可以保留6个cr读一致性块这个值的大小由隐藏参数_db_block_max_cr_dba决定它的解释是 Maximum Allowed Number of CR buffers per dba默认值是6包含5个CR块和1个XCUR块 使用SQL> show parameter _db_block_max_cr_dba查它的值没有结果 oracle的隐藏参数字典是 x$ksppi和x$ksppcv基表查询这个隐藏参数需用SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc describFROM x$ksppi x, x$ksppcv yWHERE x.inst_id = USERENV ('Instance')AND y.inst_id = USERENV ('Instance')AND x.indx = y.indxAND x.ksppinm LIKE '%_db_block_max_cr_dba%'语句结果NAME                 VALUE DESCRIB-------------------- ----- --------------------------------------------------_db_block_max_cr_dba 6     Maximum Allowed Number of CR buffers per dbaoracle给的值为6说明每个block块在CBC链上对应最多只能挂6个CR块实际测试最多有5个CR块另外1个为XCUR块 在执行了update命令的会话中将工作进行提交SQL> commit; Commit complete. 然后在两个会话中查询 SQL> selecto.object_name,  2    3  decode(state,0,'free',1,'xcur',2,'scur',3,'cr', 4,'read',5,'mrec',6,'irec',7,'write',8,'pi') state,  4    5  count(*) blocks  6  from x$bh b, dba_objects o  7  where b.obj = o.data_object_id  8  and o.object_name = 'T2'  9  group by o.object_name, state 10  order by blocks desc; OBJECT_NAME--------------------------------------------------------------------------------STATE     BLOCKS----- ----------T2cr             4 T2xcur           2结果中还有cr块说明它仍挂在CBC链上但已经失去了意义,等着被再利用。 常见的三个状态free、cr、xcur的都有了 这节讲了buffer的状态以及如何去判断buffer的状态

相关推荐