Oracle 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部落格 ” ,連結:http://blog.itpub.net/31520497/viewspace-2864956/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- [Android] 狀態機 StateMachine 原始碼剖析AndroidMac原始碼
- TodoList深入Flutter狀態管理(上篇)Flutter
- Flink 狀態管理與checkPoint資料容錯機制深入剖析-Flink牛刀小試
- buffer busy wait 的深度剖析AI
- MYSQL innodb buffer 狀態資料的儲存和載入MySql
- 深入剖析KafkaKafka
- 深入理解Flink中的狀態
- oracle狀態查詢(補)Oracle
- oracle常用狀態查詢Oracle
- oracle資料庫狀態Oracle資料庫
- 深入理解hibernate的三種狀態
- 常見的HTTP狀態碼深入理解HTTP
- AbstractQueuedSynchronizer(AQS)深入剖析AQS
- Oracle資料庫的靜默狀態和掛起狀態Oracle資料庫
- Oracle SCN健康狀態檢查Oracle
- oracle物理dg狀態檢查Oracle
- ORACLE 帳戶 狀態說明Oracle
- oracle中會話的狀態Oracle會話
- Oracle Data BufferOracle
- Buffer Busy Waits深入分析AI
- 深入剖析 Spring WebFluxSpringWebUX
- Retrofit 原始碼剖析-深入原始碼
- 深入剖析PE檔案
- oracle資料庫例項狀態Oracle資料庫
- 《深入解析Oracle》第六章,Buffer Cache與Shared Pool原理Oracle
- 關於Oracle資料庫熱備份指令碼深入剖析Oracle資料庫指令碼
- 透過Buffer cache瞭解data block在DML操作下的狀態演變BloC
- Oracle Buffer Cache原理Oracle
- Oracle database buffer cacheOracleDatabase
- 探秘Runtime - 深入剖析CategoryGo
- 深入剖析 MySQL 自增鎖MySql
- 深入剖析RocketMQ原始碼-NameServerMQ原始碼Server
- 【Go】深入剖析slice和arrayGo
- 【Go】深入剖析 slice 和 arrayGo
- numpy深入理解剖析
- 深入剖析框架之OkHttp篇框架HTTP
- 深入剖析(JDK)ArrayQueue原始碼JDK原始碼
- 深入剖析LinkedList原始碼原始碼