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日
文字:韻筝