oracle block 格式
2024-08-29 13:30:34
供稿:網友
信息參考: www.ixora.com.au
特別感謝 overtime 大哥對我的無私的幫助和對我一直鼓勵支持我的網友
這些資料是沒得到oracle 支持的 所以不能保證信息的正確性 請謹慎使用
科技無限 隨便轉載
oracle 8.1.7 8k block windows xp
create table t(n number);
insert into t values(1); --- 從 dbms_rowid 中看出table t 的數據在datafile 4 的第3個 block 上
alter system dump datafile 4 block 3;
下面是 dump 的文件的信息
還可以用下面的語句然后再用上面的 dump 語句看內存中 block 的2進制存儲格式
但這內存中的2進制格式和datafile中block數據表示的順序會略有不同可能是內存尋址的緣故吧
alter session set events '10289 trace name context forever, level 1';
alter session set events '10289 trace name context off';
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
下面的是 udump 目錄下面 dump 文件的信息
----------------------- 第一部分
buffer tsn: 7 rdba: 0x01000003 (4/3)
scn: 0x0000.000802a5 seq: 0x01 flg: 0x02 tail: 0x02a50601
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
--- buffer tsn: 數據文件對應的 tablespace 的 number 這只是dump文件中記錄的數據而已
--- block 中是沒有記錄 tablespace 的 number 的
--- rdba: 4 bytes datafile 中 block 的地址 標示的第幾個 block
--- scn: 6 bytes system change number
--- seq: 1 byte a sequence number incremented for each change to a block at the same scn
--- a new scn is allocated if the sequence number wraps.
--- 同一個scn影響這個block中的行數大于 254 行就會為這個事務分配一個新的scn
--- 如下面的操作就可能引起同一個scn但影響的同一個block 中的行超過254行
--- "delete from table_name"
--- 影響的行數(最大254) 是用從 0x01 到 0xfe 表示的
--- 當這個byte 的數據為 0xff 的時候標志這個 block 壞調了---> ora-01578
--- flg: 1 byte 1 = virgin block
--- 2 = last change to the block was for a cleanout operation
--- 4 = checksum value is set
--- 8 = temporary data
--- 這是一個可以組合的值 也就是說有為 6 的時候是 2,4 兩種情況的組合
--- tail: 4 bytes 這是記錄在 block 的最后面的 4 bytes 的數據
--- dump文件中只是把他寫在了前面而已
--- frmt: 1 byte oracle 8 以后看見的都是 0x02
--- chkval: 2 bytes 在 init 文件中設置了 db_block_checksum=true 才有值
--- type: 1 byte 這個 block 的類型 這里主要看 0x06 這種 因為這種是用來存用戶數據的
--- 其他的類型可以參考http://www.ixora.com.au/notes/cache_block_types.htm
----------------------- 第二部分
block header dump: 0x01000003
object id on block? y
seg/obj: 0x614a csc: 0x00.802a3 itc: 1 flg: o typ: 1 - data
fsl: 0 fnx: 0x0 ver: 0x01
--- seg/obj: 4 bytes 這里是16進制的 對應 sys.obj$.obj# 數據字典的數據
--- csc: 6 bytes the scn at which the last full cleanout was performed on the block
--- itc: 1 byte 下面的itl事務條的個數 8.1.7的文檔上面說可以使用 initrans 在建表的時候
--- 限制這個值的大小(max 255超過會報ora-02207) 但要考慮block 的空間是否夠
--- 表在8i中 initrans default為1 , 9.2.0中 initrans default為2
--- yong huang 說有些時候發生ora-00060可以把表的 initrans 設置大點
--- ixora 上說當block的空間不夠創建一個itl的時候一樣可能引起ora-00054
--- flg: 2 bytes 0 indicates that the block is on a freelist. otherwise the flag is -
--- 9i 的assm 的情況下這個值為 e
--- ixora 上說他占用 2 bytes 但我下面的試驗和他的結果有一定的出入
--- 我觀察到的情況是 :
--- object id on block? y
--- flg: o
--- ver: 0x01
--- 上面的3項是用同一個 byte 來表示的
--- typ: 1 byte 1 為 table ; 2 為 index. oracle進行查詢的時候是根據 obj$表中的情況來
--- 判斷對象的類型的,不是根據這個typ。也就是說如果有一個表但改變表中block
--- 的這個標志位,一樣可以查詢出數據來,但dump block 時會出錯,如下面的ora
--- ora-00600: 內部錯誤代碼,自變量: [4555], [0], [], [], [], [], [], []
--- 錯誤中的 [0] 就是typ對應的數據
--- fsl: 1 byte index to the first slot on the itl freelist. itl tx freelist slot
--- fnx: 4 bytes 自由列表中下一塊的地址 null if this block is not on a freelist
--- 有數據例如: fnx: 0x1000029
--- ver: 1 byte format (version) 這個數據沒有看到相關的文檔介紹 從ixora上說是占用1byte
--- 但我從下面的2進制文件中看到的有不同 下面有介紹
--- unused: 4 bytes 在這里還有4 bytes 的空閑的空間 但在上面的 dump 文件上是沒顯示出來的
--- 這個unused 的4 bytes是 ixora 上面的說法
--- 9i 的 assm 的 " fsl: 0 fnx: 0x0 ver: 0x01 "這一段數據的情況已經改變了
----------------------- 第三部分
itl xid uba flag lck scn/fsc
0x01 xid: 0x0003.045.000000b4 uba: 0x0080170a.00c7.36 --u- 1 fsc 0x0000.000802a5
--- 這是 oracle 用來記錄事務信息的部分 這里顯示的只有一個itl條 有多少個itl條是可以動態增加的
--- 只要 block 中的空間足夠 可以定義初始化的 itl 條的個數 用 initrans 這storage 參數
--- 這里有多少個 itl 可以從上面 "第二部分" 的 "itc:" 看出來
--- 這部分牽扯 rollback segment 或 undo tablespace
--- itl itl 的序號
--- xid: 8 bytes 值可以用select xidusn, xidslot,xidsqn from v$transaction;查到
--- this is comprised of the rollback segment number (2 bytes), the slot number
--- in the transaction table of that rollback segment (2 bytes), and the number
--- of times use of that transaction table has wrapped (4 bytes).
--- uba: 8 bytes the location of the undo for the most recent change to this block by this
--- transaction. this is comprised of the dba of the rollback segment block (4
--- bytes), the sequence number (2 bytes), and the record number for the change
--- in that undo block (1 byte), plus 1 unused byte.
--- flag 1 nibble ---- = transaction is active, or committed pending cleanout
--- c--- = transaction has been committed and locks cleaned out
--- -b-- = this undo record contains the undo for this itl entry
--- --u- = transaction committed (maybe long ago); scn is an upper bound
--- ---t = transaction was still active at block cleanout scn
--- lck 3 nibbles the number of row-level locks held in the block by this transaction.
--- scn/fsc 6 bytes if the transaction has been cleaned out, this is the commit scn or an upper
--- bound thereof. otherwise the leading two bytes contain the free space credit
--- for the transaction - that is, the number of bytes freed in the block by the
--- transaction
--- 參考http://www.ixora.com.au/q+a/datablock.htm#end
---
----------------------- 第四部分
data_block_dump
===============
tsiz: 0x1fb8
hsiz: 0x14
pbl: 0x02476c44
bdba: 0x01000003
flag=-----------
ntab=1
nrow=1
frre=-1
fsbo=0x14
fseo=0x1fb2
avsp=0x1f9b
tosp=0x1f9b
0xe:pti[0] nrow=1 offs=0
0x12:pri[0] offs=0x1fb2
--- tsiz: hsiz: pbl: bdba: 在數據文件都是沒有存儲的
--- tsiz: 除了上面的3部分和block尾部的4個字節剩下的空間 0x1fb8就是8120字節 8k的block:
--- 8192-20(block head)-24(transaction header)-24(一個事務條)-4(block tail)=8120
--- hsiz: 數據塊頭20個字節+數據塊尾4個字節=24字節(0x14)
--- pbl: ptr to buffer holding the block 我是用的專用模式dump的datafile中的block出來
--- 在同一個session的dump文件中 dump 出來的block 的這個都是同一個值
--- bdba: 和第一部分中的rdba 一個意思
--- flag 1 byte n=pctfree hit(clusters), f=don't put on free list
--- k=flushable cluster keys. 當然還有別的標記: a ...
--- ntab 1 byte 這block中有幾個table的數據 cluster這個就可能大于1
--- nrow 2 bytes block 中有多少行數據
--- frre 2 bytes first free row index entry. -1=you have to add one.
--- fsbo 2 bytes free space begin offset
--- fseo 2 bytes free space end offset
--- avsp 2 bytes available space in the block <pctfree and pctused?>
--- tosp 2 bytes total available space when all txs commit
--- 0xe: nrow 2 bytes block 中的這個table有多少行數據
--- 0xe: offs 2 bytes 偏移量 用 cluster 的時候可以看出值
----------------------- 第五部分
block_row_dump:
tab 0, row 0, @0x1fb2
tl: 6 fb: --h-fl-- lb: 0x1 cc: 1
col 0: [ 2] c1 02
end_of_block_dump
--- tl: 這條記錄中的長度 包括row head 的一般情況的 3 字節和表示數據長度的1字節和數據本身的長度
--- fb: 1 byte k = cluster key (flags may change meaning if this is set to show hash cluster)
--- c = cluster table member
--- h = head piece of row
--- d = deleted row
--- f = first data piece
--- l = last data piece
--- p = first column continues from previous piece
--- n = last column continues in next piece
--- lb: 1 byte 和上面第三部分的 itl 的lck相對應 表示這行是否被 lock 了
--- cc: 1 byte 表示這行有幾列數據
--- col 0: [ 2] : 1 byte 表示這行的這列的長度
--- c1 02 : 這就是table中的數據 "1" 可以通過下面的語句看 oracle真正使用的是
--- 那些16進制的數據來表示的用戶數據 select dump(col_name,16) from table_name;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
下面的數據就是上面的 dump 文件對應的2進制文件 我依照 2 進制數據的順序解釋內容
------------------------ 下面的對應上面dump 文件的第一部分
offset 0 1 2 3 4 5 6 7 8 9 a b c d e f
00006000 06 02 00 00 03 00 00 01 a5 02 08 00 00 00 01 02
00006010 00 00 00 00
--- 06 : type: 0x06=trans data (對應上面dump文件中的內容)
--- 02 : frmt: 0x02
--- 00 00 : filler 應該是 unused 上面的dump文件中并沒有顯示這部分內容
--- 03 00 00 01 : rdba: 0x01000003 在同一個 tablespace 中是唯一的 當 datafile 中可能不唯一
--- 來看看他的規律 :連續建4個 datafile 他們的第一block為
--- 0x 01 00 04 01
--- 0x 01 00 08 01
--- 0x 01 00 0c 01
--- 0x 01 00 00 02
--- 對應的數據在是 0x01040001 , 0x01080001 , 0x010c0001 , 0x02000001
--- 這就可以看出一個 datafile 的最大的容量是 0x01040001~0x0107ffff 總共是
--- 4m(因為還有一個datafile head)個block 如果block 是8k 一個datafile就是 32g
--- 這就是oracle 的文檔上面對 oracle 的 datafile (8k的時候)最大 32g 的原因
--- 同樣可以看出一個 tablespace 的datafile 可以從 0x0100 到 0xfffe 就是1023
--- 個 datafile 這也是 oracle 的文檔上面說一個tablesapce可以有1022 個datafile
--- 的原因(其實一個 tablespace 可以有 1023 個 datafile 我建過)
--- oracle10g中 block 的big datafile 的這段數據的情況是0x00000001~0xffffffff
--- 這也是為什么一個 big datafile 的tablesapce只有一個datafile 并且最大值為
--- 32t (8k的時候 : 4g*8k=32t ; 32k的數據塊的時候為128t)
--- a5 02 08 00 00 00 : scn: 0x0000.000802a5 oracle是c語言寫的 這6位不正好是一個 unsigned long
--- 和 unsigned int的組合
--- 01 : seq: 0x01
--- 02 : flg: 0x02
--- 00 00 : chkval: 0x0000 在 init 中設置了 db_block_checksum=true 才有值
--- 00 00 : unused 上面的dump文件中并沒有顯示這部分內容
--- 上面的20個bytes的數據任改其中的值肯定發生ora-xxxxx(不一定就是ora-01578 我還看見過ora-600)
------------------------ 下面的對應上面dump 文件的第二部分
01 00 00 00 4a 61 00 00 a3 02 08 00
00006020 00 00 00 00 01 00 03 00 00 00 00 00
--- 01 : typ: 1 - data
--- 00 : 只見過 0x00 沒見過其他的值 don't know
--- 00 : 見過有其他值 但用編輯器改這個值 在 dump 文件中顯示不出來變化
--- 00 : 沒見變過其他的值 don't know
--- 4a 61 00 00 : seg/obj: 0x614a
--- a3 02 08 00 00 00 : csc: 0x00.802a3
--- 00 00 : 見過有其他值 但用編輯器改這個值 在 dump 文件中顯示不出來變化
--- 01 : itc: 1 下面的 itl 條目的個數
--- 00 : 見過有其他值 但用編輯器改這個值 在 dump 文件中顯示不出來變化
--- 03 : flg: o ver: 0x01 object id on block? y
--- 從我的觀察中 dump 出來的文件中 flg ver object id on block
--- 他們共同占用的這個一個字節 他的規律可以從下面的情況看出
--- 2進制數據 flg ver object id on block?
--- 0x00 - 0x00 n
--- 0x01 0 0x00 n
--- 0x02 - 0x01 y
--- 0x03 0 0x01 y
--- 0x04 - 0x02 y
--- 0x05 0 0x02 y
--- 0x06 - 0x03 y
--- 0x07 0 0x03 y
--- 0x08 - 0x04 n
--- 0x09 0 0x04 n
--- 0x0a - 0x05 y
--- 0x0b 0 0x05 y
--- 0x0c - 0x06 y
--- 0x0d 0 0x06 y
--- 0x0e - 0x07 y
--- 0x0f 0 0x07 y
--- 0x10 ... 類似上面的循環了 這種情況在9i上已經改變因為assm的出現
--- 00 : fsl: 0
--- 00 00 00 00 : fnx: 0x0
------------------------ 下面的對應上面dump 文件的第三部分
03 00 45 00
00006030 b4 00 00 00 0a 17 80 00 c7 00 36 00 01 20 00 00
00006040 a5 02 08 00
--- 03 00 45 00 b4 00 00 00 : xid: 0x0003.045.000000b4
--- 0a 17 80 00 c7 00 36 00 : uba: 0x0080170a.00c7.36
--- 01 0 : lck 鎖定的row數 這里還用到了下一個 byte 的數據
--- 2 : flag 2 對應的二進制表示為 0010 正好和dump文件中的 --u- 吻合
--- 00 00 a5 02 08 00 : scn/fsc
------------------------ 下面的對應上面dump 文件的第四部分
00 01 01 00 ff ff 14 00 b2 1f 9b 1f
00006050 9b 1f 00 00 01 00 b2 1f
--- 00 : flag
--- 01 : ntab
--- 01 00 : nrow
--- ff ff : frre
--- 14 00 : fsbo
--- b2 1f : fseo
--- 9b 1f : avsp
--- 9b 1f : tosp
--- 00 00 : 0xe: offs
--- 01 00 : 0xe: nrow
--- b2 1f : 0x12:pri[0] offs=0x1fb2
------------------------ 下面的對應上面dump 文件的第五部分
--- 這部分和上面的數據中間省略了很多 因為這列子中這些部分沒存儲數據
00007ff0 00 00 00 00 00 00 2c 01 01 02 c1 02
--- 這是 block 中存用戶數據的地方
--- 2c : fb:
--- 01 : lb: 這一行是否被lock
--- 01 : 這條記錄中有多少列的數據 從這里看出因為只用一個byte去記錄這一行有多少列
--- 所以最多是255列 但一個表可以最多是1000列 如果table 的列大于255列 這里就會
--- 發生鏈接 根據一行記錄的長度來看是 塊內的鏈接或者是塊與塊直接的鏈接
--- 這也是為什么table 的設計會盡量少于255列的原因
--- 02 : 第1列的數據的長度是多少
--- c1 02 : 存儲在 block 中的數據 "1"
------------------------ 下面的對應上面dump 文件的第一部分的 "tail: 0x02a50601"
01 06 a5 02
--- 這是用來效驗 block 是否完整的標志 改這 block 最后的4 bytes 數據中的任意肯定ora-1578
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
上面只是講解了一個最簡單的oracle 的block 的格式 其他還有很多的情況 如 cluster , index 等
long , lob , long raw 這些在 block 中的表示因為數據長度的不同都會有不同的體現
有的時候改動block 中的任意數據不一定會發生 ora-01578 因為下面的兩個參數沒有設置為 true
db_block_checking db_block_checksum
這兩個參數對于system tablespace 默認都是true 所以改變 system tablespace 中的
數據肯定會發生ora-01578
隨著oracle版本的不斷升級 oracle 對block中存儲數據的正確性也在不斷的提升要求 而且通過常規的
手段想去了解 oracle block 的格式也可能越來越困難
本文來源于網頁設計愛好者web開發社區http://www.html.org.cn收集整理,歡迎訪問。