深度分析ORACLE中的塊
一直以來對“塊”的概念總是含混不清,從字面意義理解,只知道這是ORACLE存放資料的最小單位,然而它的內部世界如何呢,本人打算從今天開始連載幾篇文件,對它進行深度分析。
通過很多文件、資料,瞭解到了資料庫基本結構魚刺圖:
基本上每個物件對應一個段( Segment),只有分割槽對應多個段,這裡的物件包括table,index,partition等等,段可以跨越多個資料檔案。
每個段又有多個區(extent)來組成,這些區不能跨越多個資料檔案,同時在系統使用過程中自動擴充套件。
最後是塊(block),所有的資料都是存放在塊中。為了適應作業系統,每個塊在建立資料庫的時候預設了一個大小,這個大小一般是8K,同時在9I及其以後的版本中增加了不同大小的塊引數,這將在以後的實驗中體現。先說說這個8K大小的塊,一般來說,為了使得oracle執行讀寫資料檔案的時候有一個合理的吞吐量,這裡的塊大小,都跟作業系統塊大小設為整數倍,例如ntfs格式化的磁碟檔案,每個物理塊大小為4,這裡oracle的塊大小為8,即是代表每讀取一個oracle塊,其實物理上也就是讀取了兩個作業系統塊。這裡主要指的是資料檔案存放在塊裝置上,在實際的生產環境中,大部分情況都是將資料庫安裝在裸裝置(RAW)也叫做原始分割槽之上。關於RAW將在以後進行講解。
通過上面這段文字,我們可以瞭解到ORACLE基本的儲存結構,下一篇將針對塊的大小與存放資料大小來做實驗。
上一節瞭解到了ORACLE的儲存結構,這節講一講塊的大小與資料存放之間的關係。
大家都知道了在ORACLE環境中,所有的物件都是存放在塊中,這個塊大小與存放的記錄之間到底存在怎樣的關係呢?
做一個實驗看看:
建立一個表空間test
create tablespace test datafile '/oracle/oradata/test.dbf' size 100m;
建立一個使用者
create user test identified by test default tablespace test;
建立一個表
create table test.t1 (a1 number,a2 varchar2(100));
檢查段,可以發現在這個檢視中出現了名稱為T的段,段型別為TABLE,這個段裡面分配了1個區,其中包含8個塊,大小為64K位元組。
select segment_name,blocks,extents,bytes,segment_type,tablespace_name from dba_segments where wner='TEST';
SEGMENT_NAME BLOCKS EXTENTS BYTES SEGMENT_TYPE TABLESPACE_NAME
---------- ---------- ---------- ---------- ------------------ ----------
T 8 1 65536 TABLE TEST
檢查區,可以發現在這個檢視中出現了一個區,區號為0,包含8個塊,大小為64K位元組。
select segment_name,segment_type,extent_id,blocks,bytes from dba_extents where wner='TEST';
SEGMENT_NAME SEGMENT_TYPE EXTENT_ID BLOCKS BYTES
---------- ------------------ ---------- ---------- ----------
T TABLE 0 8 65536
檢查塊,可以發現這裡沒有載入到記憶體的塊,由此斷定,在資料未寫入的時候,記憶體中並沒有存放資料的塊。
select file#,block#,class#,status,xnc,objd from v$bh where ts#=12;
未選定行
插入10行資料,進行測試。
SQL> declare
2 i number
3 ;
4 begin
5 for i in 1..10 loop
6 execute immediate 'insert into test.t values (:x,:y)' using i,i;
7 end loop;
8 end;
9 /
PL/SQL 過程已成功完成。
再次檢視v$bh檢視,檢查記憶體中是否使用到了塊。
select file#,block#,class#,status,xnc,objd from v$bh where ts#=12;
FILE# BLOCK# CLASS# STATU XNC OBJD
---------- ---------- ---------- ----- ---------- ----------
1 28089 4 xcur 0 11038
1 28090 1 xcur 0 11038
哈哈,果然出現了資料,說明在資料插入的表的時候在記憶體中已經載入了分配的塊,同時在這些塊中寫入了資料,這裡佔用了兩個塊,塊號分別為28089,28090,其中我們可以根據CLASS#來判斷出他們屬於不同型別。
這一節緊接著上一節來說。
上一節通過實驗,我們瞭解到,塊的建立和讀取流程,不過只是針對一個會話的,現在我們來看看在一個會話中插入資料之後,同時在另外一個會話查詢資料,這樣的情況會對塊有什麼影響。
開啟一個新的會話, 然後執行如下命令:
查詢表,由於插入資料的事務沒有提交,這裡在另外的會話中就看不到任何資料,深深體現了ORACLE的多版本一致性
select * from test_gao.t;
未選定行
查詢檢視v$bh,看是否有了變化
select file#,block#,class#,status,xnc,objd from v$bh where ts#=12;
FILE# BLOCK# CLASS# STATU XNC OBJD
---------- ---------- ---------- ----- ---------- ----------
1 28089 4 xcur 0 11038
1 28090 1 cr 0 11038
1 28090 1 cr 0 11038
1 28090 1 xcur 0 11038
果然和上一節查詢出來的結果不同,多了紅色字型標識出來的兩行,大家可以看到這兩行的STATUS欄位值為cr,什麼是cr呢?它是Consistency Read(一致性讀取)的縮寫。從這裡可以看出28090這個塊被兩個會話進行了操作。
在第一個會話中回滾事務會發生什麼呢?看下面的操作:
會話1:執行rollback
SQL> rollback;
回退已完成。
再次查詢v$bh檢視,看看什麼情況
select file#,block#,class#,status,xnc,objd from v$bh where bjd=11038;
FILE# BLOCK# CLASS# STATU XNC OBJD
---------- ---------- ---------- ----- ---------- ----------
1 28089 4 xcur 0 11038
1 28090 1 cr 0 11038
1 28090 1 cr 0 11038
1 28090 1 xcur 0 11038
結果還是一樣,說明在事務回滾之後,塊還是處於一致讀取的狀態。
關閉資料庫例項
SQL> shutdown immediate
資料庫已經關閉。
已經解除安裝資料庫。
重新開啟資料庫
SQL>startup
ORACLE 例程已經啟動。
Total System Global Area 253214492 bytes
Fixed Size 454428 bytes
Variable Size 117440512 bytes
Database Buffers 134217728 bytes
Redo Buffers 1101824 bytes
資料庫裝載完畢。
資料庫已經開啟。
檢查v$bh檢視
select file#,block#,class#,status,xnc,objd from v$bh where bjd=11038;
未選定行
說明在沒有進行塊中資料的相關操作的時候,並沒有從物理檔案中提取塊到記憶體。
執行查詢或者插入、更新的SQL語句
SQL> insert into test.t values (200,200);
已建立 1 行。
再次檢查v$bh檢視
SQL> select file#,block#,class#,status,xnc,objd from v$bh where bjd=11038;
FILE# BLOCK# CLASS# STATU XNC OBJD
---------- ---------- ---------- ----- ---------- ----------
1 28089 4 xcur 0 11038
1 28090 1 xcur 0 11038
總結:在沒有進行物理I/O的時候,v$bh檢視中不會出現相關的塊資訊,同時證明此檢視中存放的乃是資料檔案塊放到記憶體中的“塊”資訊。
轉儲塊資料,使用這條命令
alter system dump datafile 12 block 28090;
系統已更改。
在相應的目錄下找出trace檔案
一般trace檔案都存放在$ORACLE_BASE/admin/SID/udump目錄下,這裡我們找到剛剛轉儲的檔案o9i_ora_300.trc
開啟這個檔案,列出部分內容:
Dump file c:\oracle\admin\o9i\udump\o9i_ora_300.trc
Wed Jun 18 09:12:17 2008
ORACLE V9.2.0.4.0 - Production vsnsta=0
vsnsql=12 vsnxtr=3
Windows 2000 Version 5.1 Service Pack 2, CPU type 586
Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production
Windows 2000 Version 5.1 Service Pack 2, CPU type 586
Instance name: o9i
Redo thread mounted by this instance: 1
Oracle process number: 10
Windows thread id: 300, image: ORACLE.EXE
*** 2008-06-18 09:47:34.031
Start dump data blocks tsn: 0 file#: 1 minblk 28090 maxblk 28090
buffer tsn: 0 rdba: 0x00406dba (1/28090)
scn: 0x0000.000c0a29 seq: 0x01 flg: 0x00 tail: 0x0a290601
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Block header dump: 0x00406dba
Object id on Block? Y
seg/obj: 0x2b1e csc: 0x00.c0a29 itc: 2 flg: O typ: 1 - DATA
fsl: 0 fnx: 0x0 ver: 0x01
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0009.019.000000e5 0x00801ea9.0045.0d C--- 0 scn 0x0000.000b9373
0x02 0x0006.005.000000e0 0x00804605.0051.2c C--- 0 scn 0x0000.000badb9
data_block_dump,data header at 0x347105c
===============
tsiz: 0x1fa0
hsiz: 0x26
pbl: 0x0347105c
bdba: 0x00406dba
76543210
flag=--------
ntab=1
nrow=10
frre=4
fsbo=0x26
fseo=0x1e96
avsp=0x1f56
tosp=0x1f56
0xe:pti[0] nrow=10 ffs=0
0x12:pri[0] ffs=0x1eb6
0x14:pri[1] ffs=0x1eae
0x16:pri[2] ffs=0x1ea6
0x18:pri[3] ffs=0x1e96
0x1a:pri[4] sfll=5
0x1c:pri[5] sfll=6
0x1e:pri[6] sfll=7
0x20:pri[7] sfll=8
0x22:pri[8] sfll=9
0x24:pri[9] sfll=-1
block_row_dump:
tab 0, row 0, @0x1eb6
tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
col 0: [ 2] c1 02
col 1: [ 1] 32
tab 0, row 1, @0x1eae
tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
col 0: [ 2] c1 02
col 1: [ 1] 32
tab 0, row 2, @0x1ea6
tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
col 0: [ 2] c1 02
col 1: [ 1] 32
tab 0, row 3, @0x1e96
tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
col 0: [ 2] c1 02
col 1: [ 1] 33
end_of_block_dump
End dump data blocks tsn: 0 file#: 1 minblk 28090 maxblk 28090
tsiz: 0x1fa0 塊大小,轉為10進位制是8096
hsiz: 0x26 頭大小,轉為10進位制是38
tab 0, row 0, @0x1eb6
tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
col 0: [ 2] c1 02
col 1: [ 1] 32
tab 0, row 1, @0x1eae
tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
col 0: [ 2] c1 02
col 1: [ 1] 32
tab 0, row 2, @0x1ea6
tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
col 0: [ 2] c1 02
col 1: [ 1] 32
tab 0, row 3, @0x1e96
tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
col 0: [ 2] c1 02
col 1: [ 1] 33
這寫資料表示了每條記錄的每個列內資料 ,紅色字型標識出來的全部一樣,說明這四行資料完全相同,只有第四條記錄(藍色標識)的那一列不同,為什麼呢?
查詢表中的資料確定答案
select * from test.t;
A1 A2
---------- ----------
1 2
1 2
1 2
1 3
相信看了這個查詢結果,我們都能明白了,前3行資料完全一樣,第四行資料中第2列與前三行不同。
這裡的 c1 02 代表 1,32代表2,33代表3。
再來說說黃色字型,表示當前塊的第一個tab,四行資料,同時標識出了當前這行資料的指標。
@0x1eb6,@0x1eae,@0x1ea6,@0x1e96;7862,7854,7846,7830 這四個值分別對應了四條資料的指標,根據這個指標我們可以找到相應的值。
V$BH是BUFFER HEAD的檢視。其基表是X$BH,這是目前能夠找到的X$BH的說明中最新的版本:
Column Type Description
~~~~~~ ~~~~~ ~~~~~~~~~~~
ADDR RAW(4) Hex address of the Buffer Header.
INDX NUMBER Buffer Header number
BUF# NUMBER
HLADDR RAW(4) Hash Chain Latch Address
See
LRU_FLAG NUMBER 8.1+ LRU flag
KCBBHLDF 0x01 8.1 LRU Dump Flag used in debug print routine
KCBBHLMT 0x02 8.1 moved to tail of lru (for extended stats)
KCBBHLAL 0x04 8.1 on auxiliary list
KCBBHLHB 0x08 8.1 hot buffer - not in cold portion of lru
FLAG NUMBER
KCBBHFBD 0x00001 buffer dirty
KCBBHFAM 0x00002 7.3 about to modify; try not to start io
KCBBHFAM 0x00002 8.0 about to modify; try not to start io
KCBBHNAC 0x00002 8.1 notify dbwr after change
KCBBHFMS 0x00004 modification started, no new writes
KCBBHFBL 0x00008 block logged
KCBBHFTD 0x00010 temporary data - no redo for changes
KCBBHFBW 0x00020 being written; can't modify
KCBBHFWW 0x00040 waiting for write to finish
KCBBHFCK 0x00080 7.3 checkpoint asap
0x00080 8.0 not used
KCBBHFMW 0x00080 8.1 multiple waiters when gc lock acquired
KCBBHFRR 0x00100 recovery reading, do not reuse, being read
KCBBHFUL 0x00200 unlink from lock element - make non-current
KCBBHFDG 0x00400 write block & stop using for lock down grade
KCBBHFCW 0x00800 write block for cross instance call
KCBBHFCR 0x01000 reading from disk into KCBBHCR buffer
KCBBHFGC 0x02000 has been gotten in current mode
KCBBHFST 0x04000 stale - unused CR buf made from current
0x08000 7.3 Not used.
KCBBHFDP 0x08000 8.0 deferred ping
KCBBHFDP 0x08000 8.1 deferred ping
KCBBHFDA 0x10000 Direct Access to buffer contents
KCBBHFHD 0x20000 Hash chain Dump used in debug print routine
KCBBHFIR 0x40000 Ignore Redo for instance recovery
KCBBHFSQ 0x80000 sequential scan only flag
KCBBHFNW 0x100000 7.3 Set to indicate a buffer that is NEW
0x100000 8.0 Not used
KCBBHFBP 0x100000 8.1 Indicates that buffer was prefetched
KCBBHFRW 0x200000 7.3 re-write if being written (sort)
0x200000 8.0 Not used
KCBBHFFW 0x200000 8.1 Buffer has been written once
KCBBHFFB 0x400000 buffer is "logically" flushed
KCBBHFRS 0x800000 ReSilvered already - do not redirty
KCBBHFKW 0x1000000 7.3 ckpt writing flag to avoid rescan */
0x1000000 8.0 Not used
KCBBHDRC 0x1000000 8.1 buffer is nocache
0x2000000 7.3 Not used
KCBBHFRG 0x2000000 8.0 Redo Generated since block read
KCBBHFRG 0x2000000 8.1 Redo Generated since block read
KCBBHFWS 0x10000000 8.0 Skipped write for checkpoint.
KCBBHFDB 0x20000000 8.1 buffer is directly from a foreign DB
KCBBHFAW 0x40000000 8.0 Flush after writing
KCBBHFAW 0x40000000 8.1 Flush after writing
TS# NUMBER 8.X Tablespace number
DBARFIL NUMBER 8.X Relative file number of block
DBAFIL NUMBER 7.3 File number of block
DBABLK NUMBER Block number of block
CLASS NUMBER See Note 33434.1
STATE NUMBER
KCBBHFREE 0 buffer free
KCBBHEXLCUR 1 buffer current (and if DFS locked X)
KCBBHSHRCUR 2 buffer current (and if DFS locked S)
KCBBHCR 3 buffer consistant read
KCBBHREADING 4 Being read
KCBBHMRECOVERY 5 media recovery (current & special)
KCBBHIRECOVERY 6 Instance recovery (somewhat special)
MODE_HELD NUMBER Mode buffer held in (MODE pre 7.3)
0=KCBMNULL, KCBMSHARE, KCBMEXCL
CHANGES NUMBER
CSTATE NUMBER
X_TO_NULL NUMBER Count of PINGS out (OPS)
DIRTY_QUEUE NUMBER You wont normally see buffers on the LRUW
LE_ADDR RAW(4) Lock Element address (OPS)
SET_DS RAW(4) Buffer cache set this buffer is under
OBJ NUMBER Data object number
TCH NUMBER 8.1 Touch Count
TIM NUMBER 8.1 Touch Time
BA RAW(4)
CR_SCN_BAS NUMBER Consistent Read SCN base
CR_SCN_WRP NUMBER Consistent Read SCN wrap
CR_XID_USN NUMBER CR XID Undo segment no
CR_XID_SLT NUMBER CR XID slot
CR_XID_SQN NUMBER CR XID Sequence
CR_UBA_FIL NUMBER CR UBA file
CR_UBA_BLK NUMBER CR UBA Block
CR_UBA_SEQ NUMBER CR UBA sequence
CR_UBA_REC NUMBER CR UBA record
CR_SFL NUMBER
LRBA_SEQ NUMBER } Lowest RBA needed to recover block in cache
LRBA_BNO NUMBER }
LRBA_BOF NUMBER }
HRBA_SEQ NUMBER } Redo RBA to be flushed BEFORE this block
HRBA_BNO NUMBER } can be written out
HRBA_BOF NUMBER }
RRBA_SEQ NUMBER } Block recovery RBA
RRBA_BNO NUMBER }
RRBA_BOF NUMBER }
NXT_HASH NUMBER Next buffer on this hash chain
PRV_HASH NUMBER Previous buffer on this hash chain
NXT_LRU NUMBER Next buffer on the LRU
PRV_LRU NUMBER Previous buffer on the LRU
US_NXT RAW(4)
US_PRV RAW(4)
WA_NXT RAW(4)
WA_PRV RAW(4)
ACC RAW(4)
MOD RAW(4)
對於9.2.0.1 BH的資料結構為:
{
kgglk kcbbhha; /* hash chain buffer is on */
ktsn kcbbhtsn; /* tablespace number */
krdba kcbbhrdba; /* relative DBA */
ub4 kcbbhflg; /* flags: all changes require hash latch */
b1 kcbbhst; /* state of the buffer */
b1 kcbbhmd; /* mode owned in (KCBMNULL, KCBMSHR, KCBMEXCL) */
word kcbbhcla; /* block class */
kfil kcbbhafn; /* absolute file number */
kobjd kcbbhobj; /* Object # (disk )for block (if known) */
kobjn kcbbhobjn; /* dictionary object # (if known) */
ptr_t kcbbhba; /* buffer base address (set when mapped) */
kscn kcbbhdscn; /* incremental Transactional DSCN */
kgglk kcbbhus; /* list of buffers using queue */
kgglk kcbbhwa; /* list of buffers waiting */
b1 kcbbhccnt; /* number of changes to buffer in single kcbchg() */
b1 kcbbhcst; /* change state for recovery if failure during kcbchg() */
kgglk kcbbhrpl; /* link for maintaining position on replacement chain */
b1 kcbbhfoq; /* TRUE iff the buffer is on a write list */
b1 kcbbhlpf; /* LRU latch protected flags */
ub2 kcbbhtch; /* touch count */
ub4 kcbbhtim; /* time of last touch count increment */
kcrda kcbbhlrba; /* lowest rba needed to recover block on disk */
kcrda kcbbhrrba; /* lowest rba needed to recover block in cache */
kcbcr kcbbhcr; /* consistent read fields */
kssob * kcbbhrsop; /* recovery s.o.; for recovery buffers only */
kcrfkd kcbbhhfkd; /* SCN of the highest change in the buffer */
ub2 kcbbhdbc; /* delayed block cleanout count */
ub2 kcbbhssid;
ub2 kcbbhcqid; /* which ckpt queue in working set buffer is */
kgglk kcbbhckql; /* link for checkpoint queue */
kgglk kcbbhfql; /* link for per-file checkpoint queue */
struct kcbwds * kcbbhds; /* system set descriptor */
struct kcbbh.UNK_lch_kcbbhsh UNK_lch_kcbbhsh; /* all fields that are needed in shared mode */
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24558279/viewspace-746173/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 深度分析ORACLE熱點塊問題Oracle
- 深度分析ORACLE熱點塊問題(轉)Oracle
- 深度分析資料庫的熱點塊問題資料庫
- 深度分析資料庫的熱點塊問題(轉)資料庫
- 深度分析資料庫的熱點塊問題 (zt)資料庫
- 關於 Java 中 finally 語句塊的深度辨析Java
- Java中對HashMap的深度分析與比較JavaHashMap
- 深度分析C#中Array的儲存結構C#
- Java中對HashMap的深度分析與比較(轉)JavaHashMap
- 深度分析資料庫的熱點塊問題(作者:biti_rainy )資料庫AI
- Oracle資料庫壞塊典型案例分析Oracle資料庫
- 【深度學習】深度解讀:深度學習在IoT大資料和流分析中的應用深度學習大資料
- 深度分析如何在Hadoop中控制Map的數量Hadoop
- 索引在ORACLE中的應用分析索引Oracle
- HashMap深度分析HashMap
- memcached深度分析
- 教你如何處理Oracle資料庫中的壞塊Oracle資料庫
- ORACLE中修復資料塊損壞Oracle
- 轉抄:Oracle資料塊深入分析總結Oracle
- Gifto(GTO)分析NFT中區塊鏈技術的連線區塊鏈
- 區塊鏈中的共識機制分析與對比區塊鏈
- ORACLE中seq$表更新頻繁的分析Oracle
- 中信建投:產業區塊鏈行業現狀深度分析(附下載)產業區塊鏈行業
- Oracle (block clean out) oracle的塊清除OracleBloC
- Oracle RMAN備份中對壞塊(corrupt block)的處理OracleBloC
- 深度理解Oracle10g中UNDO_RETENTION引數的使用Oracle
- 【深度長文】循序漸進解讀Oracle AWR效能分析報告Oracle
- oracle 塊清除Oracle
- 如何處理Oracle資料庫中的壞塊問題(轉)Oracle資料庫
- [zt] 如何處理Oracle資料庫中的壞塊[final]Oracle資料庫
- 資料塊分析
- oracle資料塊dump檔案中ITL詳解Oracle
- Oracle中匯出修復資料塊損壞Oracle
- Oracle中模擬修復資料塊損壞Oracle
- Oracle上的邏輯壞塊和物理壞塊Oracle
- Oracle 中的 ROW_NUMBER() OVER() 分析函式的用法Oracle函式
- 深度理解Oracle10g中UNDO_RETENTION引數的使用(轉)Oracle
- 深度學習中的Dropout深度學習