ITPub博客

首页 > 数据库 > Oracle > Oracle buffer状态深入剖析

Oracle buffer状态深入剖析

Oracle 作者:Davis_itpub 时间:2022-03-05 19:10:48 0 删除 编辑

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 image

1, XCUR, a current mode block, exclusive to this instance

2, SCUR, a current mode block, shared with other instances

3, CR, a consistent read (stale) block image

4, READ, buffer is reserved for a block being read from disk

5, MREC, a block in media recovery mode

6, 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和SCUR

X是exclusive(独占的)的缩写

S是shared(共享的)的缩写



我们讲过一个数据库一般都有一个实例

但是也有一个数据库对应多个实例



一个数据库对应一个实例的情况下也就是在非RAC的环境下

current永远都用XCUR也就是只有XCUR

因为这个buffer块被这个实例独占



如果在存在RAC的环境里面才有可能出现SCUR

RAC中有Cache Fusion(融合)即内存融合技术

也叫PCM:Parallel Cache Management并发内存管理

SCUR在Cache Fusion技术机制会用到

因为它需要和其它进程分享这个buffer块



在单实例环境里面

current只有一种情况就是XCUR

SCUR在非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的几种状态




三)查询块状态的例子


举一个例子

现在有个表t2

SQL> select * from t2;


        ID NAME

---------- --------------------

         1 xkj

         2 jiagulun


t2现在有两个数据行



然后

SQL> alter system flush buffer_cache;


System altered.



这是将整个buffercache全部清空

这样可以清楚的看到sql语句生成的buffer的个数和状态

但这在生产中是比较危险的

因为你全部清空以后接着会发生大量的物理io



使用下面语句

select

o.object_name,

decode(state,0,'free',1,'xcur',2,'scur',3,'cr', 4,'read',5,'mrec',

6,'irec',7,'write',8,'pi') state,

count(*) blocks

from x$bh b, dba_objects o

where b.obj = o.data_object_id

and o.object_name = 'T2'

group by o.object_name, state

order by blocks desc;

能查一个对象所占用buffer的情况



我们查t2表

SQL> select

o.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

----- ----------

T2

free           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> select

o.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

----- ----------

T2

xcur           2


T2

free           2



结果中t2占了两个块是xcur

对这个块读的话也是xcur

free的两个块不是真实的它并没有占用



执行语句:

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> select

o.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

where 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

----- ----------

T2

xcur           2


T2

cr             2


T2

free           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 describ

FROM x$ksppi x, x$ksppcv y

WHERE x.inst_id = USERENV ('Instance')

AND y.inst_id = USERENV ('Instance')

AND x.indx = y.indx

AND x.ksppinm LIKE '%_db_block_max_cr_dba%'

语句

结果

NAME                 VALUE DESCRIB

-------------------- ----- --------------------------------------------------

_db_block_max_cr_dba 6     Maximum Allowed Number of CR buffers per dba

oracle给的值为6说明每个block块在CBC链上对应最多只能挂6个CR块

实际测试最多有5个CR块另外1个为XCUR块



在执行了update命令的会话中将工作进行提交

SQL> commit;


Commit complete.



然后在两个会话中查询



SQL> select

o.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

----- ----------

T2

cr             4


T2

xcur           2

结果中还有cr块说明它仍挂在CBC链上但已经失去了意义,等着被再利用。



常见的三个状态free、cr、xcur的都有了




这节讲了buffer的状态以及如何去判断buffer的状态




来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31520497/viewspace-2864956/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2018-02-07

  • 博文量
    205
  • 访问量
    218782