天天看點

oracle學習筆記 buffer狀态深入剖析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

說面目前這個表中

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的狀态

2016年9月25日

                                          文字:韻筝