資料塊結構
Oracle 資料塊有三部分:
Cache layer
Transaction layer
Data layer
Oracle Data Block的結構簡圖如下,其中從Data header到Row Data部分合稱Data Layer:
- Cache Layer -
- Transaction Layer -
- Data Header -
- Table Directory -
- Row Directory -
- Free Space -
- Row Data -
- Tailchk -
下面将使用bbed工具來顯示相關結構資訊
BBED> map
File: /u01/app/oracle/oradata/shardcat/users01.dbf (7)
Block: 135 Dba:0x01c00087
KTB Data Block (Table/Cluster)
struct kcbh, 20 bytes @0
struct ktbbh, 72 bytes @20
struct kdbh, 14 bytes @100
struct kdbt[1], 4 bytes @114
sb2 kdbr[8] @118
ub1 freespace[7983] @134
ub1 rowdata[71] @8117
ub4 tailchk @8188
資料塊元件
Oracle資料塊三層C結構,它被映射到SGA kcbh(核心緩存資料塊頭)中的資料塊。Cache Layer包含關于塊格式,類型(資料,索引,頭等)資訊和序列資料。
BBED> p kcbh
struct kcbh, 20 bytes @0
ub1 type_kcbh @0 0x06
ub1 frmt_kcbh @1 0xa2
ub2 wrp2_kcbh @2 0x0000
ub4 rdba_kcbh @4 0x01c00087
ub4 bas_kcbh @8 0x01286184
ub2 wrp_kcbh @12 0x0000
ub1 seq_kcbh @14 0x01
ub1 flg_kcbh @15 0x06 (KCBHFDLC, KCBHFCKV)
ub2 chkval_kcbh @16 0x0137
ub2 spare3_kcbh @18 0x0000
Cache Layer:Block的第一部分,長度為20位元組,内部資料結構名為kcbh,包括
type_kcbh:塊類型(table/index,rollback segment,temporary segment等)
frmt_kcbh:塊格式(v6,v7,v8)
rdba_kcbh:塊位址DBA
bas_kcbh/wrp_kcbh:SCN
seq_kcbh:塊的序列号
flg_kcbh:塊的标志
事務層存儲了關于資料塊的事務資訊
Transaction Layer:内部結構名ktbbh。分成兩部分,第一部分為固定長度,長度為24位元組,包含事務相關的一些基本資訊。第二部分為可變長度,包含itl,長度根據itl條目的個數變化,每個itl長度為24位元組,内部結構名ktbbhitl
BBED> p ktbbh
struct ktbbh, 72 bytes @20
ub1 ktbbhtyp @20 0x01 (KDDBTDATA)
union ktbbhsid, 4 bytes @24
ub4 ktbbhsg1 @24 0x0001af27
ub4 ktbbhod1 @24 0x0001af27
struct ktbbhcsc, 8 bytes @28
ub4 kscnbas @28 0x01286182
ub2 kscnwrp @32 0x8000
ub2 kscnwrp2 @34 0x0000
sb2 ktbbhict @36 7938
ub1 ktbbhflg @38 0x32 (NONE)
ub1 ktbbhfsl @39 0x00
ub4 ktbbhfnx @40 0x01c00080
struct ktbbhitl[0], 24 bytes @44
struct ktbitxid, 8 bytes @44
ub2 kxidusn @44 0x0006
ub2 kxidslt @46 0x0012
ub4 kxidsqn @48 0x000038f6
struct ktbituba, 8 bytes @52
ub4 kubadba @52 0x010002d9
ub2 kubaseq @56 0x10c9
ub1 kubarec @58 0x09
ub2 ktbitflg @60 0x8000 (KTBFCOM)
union _ktbitun, 2 bytes @62
sb2 _ktbitfsc @62 -32768
ub2 _ktbitwrp @62 0x8000
ub4 ktbitbas @64 0x01228dbb
struct ktbbhitl[1], 24 bytes @68
struct ktbitxid, 8 bytes @68
ub2 kxidusn @68 0x0008
ub2 kxidslt @70 0x001b
ub4 kxidsqn @72 0x00003a9a
struct ktbituba, 8 bytes @76
ub4 kubadba @76 0x010002b5
ub2 kubaseq @80 0x114f
ub1 kubarec @82 0x20
ub2 ktbitflg @84 0x2001 (KTBFUPB)
union _ktbitun, 2 bytes @86
sb2 _ktbitfsc @86 10
ub2 _ktbitwrp @86 0x000a
ub4 ktbitbas @88 0x01286184
這種結構出現在資料庫每個資料塊的開頭部分。它甚至出現在不由redo改變的排序塊中。它也會出現在資料檔案頭塊和控制檔案頭塊的開頭部分。緩存層提供了對壞資料的規模。它也用來確定正确的資料塊被讀取并且資料塊沒有破裂或損壞。所謂破裂的資料塊就是隻有一部分被寫入磁盤,資料塊的一部分保留了之前的版本。
Data Layer:包括Data Header,Table Directory,Row Directory,Free Space和Row Data。
Data Header:長度14位元組,内部資料結構名kdbh
BBED> p kdbh
struct kdbh, 14 bytes @100
ub1 kdbhflag @100 0x00 (NONE)
sb1 kdbhntab @101 1
sb2 kdbhnrow @102 8
sb2 kdbhfrre @104 -1
sb2 kdbhfsbo @106 34
sb2 kdbhfseo @108 8017
sb2 kdbhavsp @110 7977
sb2 kdbhtosp @112 7989
其中kdbhnrow是存儲在資料塊中的記錄數為8,而表中确實有8條記錄。(從ROWID可以判斷出來)
SQL> select dbms_rowid.rowid_block_number(rowid),t1.t_id,t1.t_name from jy.t1;
DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) T_ID T_NAME
------------------------------------ ---------- ----------------------------------------
134 9 YYL
135 1 A
135 2 B
135 3 C
135 4 D
135 5 E
135 6 F
135 7 JYHY
135 8 JYYYL
9 rows selected.
Table Directory: 一般table隻有一個條目,cluster則有一個或多個條目。每個條目長4位元組,内部資料結構名kdbt
BBED> p kdbt
struct kdbt[0], 4 bytes @114
sb2 kdbtoffs @114 0
sb2 kdbtnrow @116 8
Row Directory:數目由塊中資料的行數決定,每個條目長2位元組,内部資料結構名kdbr
BBED> p kdbr
sb2 kdbr[0] @118 8080
sb2 kdbr[1] @120 8072
sb2 kdbr[2] @122 8064
sb2 kdbr[3] @124 8056
sb2 kdbr[4] @126 8048
sb2 kdbr[5] @128 8040
sb2 kdbr[6] @130 8029
sb2 kdbr[7] @132 8017
檢視表中的記錄資料,一個重複計數也可以被指定用來重複執行examine指令來檢查後續的行記錄。下面的例子顯示了先使用print指令來設定最後一行記錄的偏移量,然後檢查後面的8行記錄的操作.
BBED> p *kdbr[7]
rowdata[0]
ub1 rowdata[0] @8117 0x2c
BBED> x /8rnc
rowdata[0] @8117
flag@8117: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8118: 0x02
cols@8119: 2
col 0[2] @8120: 8
col 1[5] @8123: JYYYL
rowdata[12] @8129
flag@8129: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8130: 0x00
cols@8131: 2
col 0[2] @8132: 7
col 1[4] @8135: JYHY
rowdata[23] @8140
flag@8140: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8141: 0x00
cols@8142: 2
col 0[2] @8143: 6
col 1[1] @8146: F
rowdata[31] @8148
flag@8148: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8149: 0x00
cols@8150: 2
col 0[2] @8151: 5
col 1[1] @8154: E
rowdata[39] @8156
flag@8156: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8157: 0x00
cols@8158: 2
col 0[2] @8159: 4
col 1[1] @8162: D
rowdata[47] @8164
flag@8164: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8165: 0x00
cols@8166: 2
col 0[2] @8167: 3
col 1[1] @8170: C
rowdata[55] @8172
flag@8172: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8173: 0x00
cols@8174: 2
col 0[2] @8175: 2
col 1[1] @8178: B
rowdata[63] @8180
flag@8180: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8181: 0x00
cols@8182: 2
col 0[2] @8183: 1
col 1[1] @8186: A
Free Space:表示資料塊中可用空間,内部資料結構名freespace
Row Data:表示實際的資料,内部資料結構名rowdata
BBED> p rowdata[0]
BBED> d /v offset 8117
Block: 135 Offsets: 8117 to 8191 Dba:0x01c00087
2c020202 c109054a 5959594c 2c000202 l ,......JYYYL,...
c108044a 5948592c 000202c1 0701462c l ...JYHY,......F,
000202c1 0601452c 000202c1 0501442c l ......E,......D,
000202c1 0401432c 000202c1 0301422c l ......C,......B,
000202c1 02014101 068461 l ......A...a
<16 bytes per line>
Tailchk:儲存在塊結尾用于校驗的資料,長度4個位元組,内部結構名tailchk。所有Oracle塊的最後四個位元組都是tail check(結尾檢查)。
對于一個Oracle 8以上版本的資料塊的tail它是由SCN base的低位兩位元組的内容,資料塊的類型與SCN序列号組成的。例如,如果SCN base為 0x01286184,資料塊類型為0x06,SCN序列号為0x01,那麼tail check将是0x61840601
BBED> p tailchk
ub4 tailchk @8188 0x61840601
雖然tail check的值通常是由這三個元件級成,Oracle會對最終的值作為一個值(4位元組)以單無符号整數來存儲。在小位元組序編碼(little-endian)的構架機器中,比如Intel,這個值将以低位位元組優先的方式來存儲。是以如果使用标準塊編輯器或dump指令來檢查資料塊的tail check時,位元組順序可能不一樣。一個tail check為0x61840601,在Intel機器上它将以"01068461"的形式存儲在磁盤。
BBED> dump /v offset 8188
Block: 135 Offsets: 8188 to 8191 Dba:0x01c00087
01068461 l ...a