BBED是Oracle提供的块编辑器,借助BBED,可以帮助我们更好的理解Oracle的Block的结构。
当然,反过来说,也只有更加理解块的结构,才能更好的利用BBED完成某些特殊情况下的灾难恢复。、
Oracle Data Block的结构简图如下,其中从Data header到Row Data部分合称Data Layer:
--------------------- - Cache Layer - --------------------- - Transaction Layer - --------------------- --| - Data Header - | --------------------- | - Table Directory - | --------------------- | - Row Directory - | --------------------- ---从Data header到Row Data部分合称Data Layer - Free Space - | --------------------- | - Row Data - | --------------------- --| - Tailchk - ---------------------
BBED> set file 4 block 355 FILE# 4 BLOCK# 355 BBED> map File: /u01/oradata/ORCL/datafile/o1_mf_users_c059cg60_.dbf (4) Block: 355 Dba:0x01000163 ------------------------------------------------------------ KTB Data Block (Table/Cluster) struct kcbh, 20 bytes @0 <<<<<< cache layer struct ktbbh, 96 bytes @20 struct kdbh, 14 bytes @124 struct kdbt[1], 4 bytes @138 sb2 kdbr[10] @142 ub1 freespace[7111] @162 ub1 rowdata[915] @7273 ub4 tailchk @8188
========================================================================================
1、理解数据块头结构
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:块的标志
BBED> p kcbh
> p kcbh
kcbh, 20 bytes @0
ub1 type_kcbh @0 0x06 <<<<< Block Type
--0 = none.
--0 = none.
--1 = KTU UNDO HEADER
--1 = KTU UNDO HEADER
--2 = KTU UNDO BLOCK
--2 = KTU UNDO BLOCK
--3 = SAVE UNDO HDR
--3 = SAVE UNDO HDR
--4 = SAVE UNDO BLOCK
--4 = SAVE UNDO BLOCK
--5 = DATA SEG HDR
--5 = DATA SEG HDR
--6 = KTB MANAGED (with ITL)
--6 = KTB MANAGED (with ITL)
--7 = TEMP DATA (no itl)
--7 = TEMP DATA (no itl)
--8 = SORT KEY
--8 = SORT KEY
--9 = SORT RUN
--9 = SORT RUN
--10 = SEG FREE LIST
--10 = SEG FREE LIST
--11 = DATA FILE HDR
--11 = DATA FILE HDR
--12 = DATA SEG HDR with Free List Groups
--12 = DATA SEG HDR with Free List Groups
--13 = Compatibility SEG
--13 = Compatibility SEG
--14 = unlimited undo segment header
--14 = unlimited undo segment header
--15 = unlimited save undo segment header
--15 = unlimited save undo segment header
--16 = unlimited data segment header
--16 = unlimited data segment header
--17 = unlimited data segment header with flg blks
--17 = unlimited data segment header with flg blks
--18 = extent map block
--18 = extent map block
--19 = backup set piece header
--19 = backup set piece header
--20 = backup set directory block
--20 = backup set directory block
--21 = control file block
--21 = control file block
--22 = segment free list block with #blks in freelists
--22 = segment free list block with #blks in freelists
--23 = bitmapped segment header
--23 = bitmapped segment header
--24 = bitmapped freelist block
--24 = bitmapped freelist block
--25 = bitmap index block
--25 = bitmap index block
--26 = bitmap block
--26 = bitmap block
--27 = LOB block
--27 = LOB block
--28 = funny undo block (for future use)
--28 = funny undo block (for future use)
--29 = bitmapped file space header
--29 = bitmapped file space header
--30 = bitmapped file space bitmap block
--30 = bitmapped file space bitmap block
--31 = temporary seg based index
--31 = temporary seg based index
--32 = First level bitmap block
--32 = First level bitmap block
--33 = second level bitmap block
--33 = second level bitmap block
--34 = third level bitmap block
--34 = third level bitmap block
--35 = Pagetable segment header block
--35 = Pagetable segment header block
--36 = Pagetable extent map block
--36 = Pagetable extent map block
--37 = System Managed Undo Extent Map Block
--37 = System Managed Undo Extent Map Block
--38 = System Managed Segment Header Block
--38 = System Managed Segment Header Block
--39 = SPFILE backup block
--39 = SPFILE backup block
--40 = pagetable managed LOB block
--40 = pagetable managed LOB block
--41 = max value for block header validation
--41 = max value for block header validation
ub1 frmt_kcbh @1 0xa2 <<<<< Block Format 1=Oracle7, 2=Oracle8+
ub1 spare1_kcbh @2 0x00 <<<<< Not used, filler field
ub1 spare1_kcbh @2 0x00 <<<<< Not used, filler field
ub1 spare2_kcbh @3 0x00 <<<<< Not used, filler field
ub1 spare2_kcbh @3 0x00 <<<<< Not used, filler field
ub4 rdba_kcbh @4 0x01000163 <<<<< RDBA (4 bytes) - Relative Data Block Address -- 该块的相对数据库地址,共 32 位,高 10 位表示相对文件号,低 22位表示块号
ub4 rdba_kcbh @4 0x01000163 <<<<< RDBA (4 bytes) - Relative Data Block Address -- 该块的相对数据库地址,共 32 位,高 10 位表示相对文件号,低 22位表示块号
ub4 bas_kcbh @8 0x800330d0 <<<<< SCN Base (4 bytes)
ub4 bas_kcbh @8 0x800330d0 <<<<< SCN Base (4 bytes)
ub2 wrp_kcbh @12 0x0000 <<<<< SCN Wrap (2 bytes) --对应着当前 REDO 生成的 SCN, SCN 由 SCN BASE 和 SCN WRAP 两部分组成
ub2 wrp_kcbh @12 0x0000 <<<<< SCN Wrap (2 bytes) --对应着当前 REDO 生成的 SCN, SCN 由 SCN BASE 和 SCN WRAP 两部分组成
ub1 seq_kcbh @14 0x01 <<<<< Sequence Number, 在相同的 SCN 下,该块可能会产生多次变化,
ub1 seq_kcbh @14 0x01 <<<<< Sequence Number, 在相同的 SCN 下,该块可能会产生多次变化,
使用序列号进行区分,如果 SCN 增长,序列号复位为 1。
使用序列号进行区分,如果 SCN 增长,序列号复位为 1。
ub1 flg_kcbh @15 0x04 (KCBHFCKV) <<<<<Flag
ub1 flg_kcbh @15 0x04 (KCBHFCKV) <<<<<Flag
--KCBHFNEW 0x01 // 新建块
--KCBHFNEW 0x01 // 新建块
--KCBHFDLC 0x02 // 数据块延迟清洗推进 SCN 和序列号
--KCBHFDLC 0x02 // 数据块延迟清洗推进 SCN 和序列号
--KCBHFCKV 0x04 // 设置校验和
--KCBHFCKV 0x04 // 设置校验和
-- KCBHFTMP 0x08 // 临时块
-- KCBHFTMP 0x08 // 临时块
ub2 chkval_kcbh @16 0x9107 <<<<< Optional block checksum (if DB_BLOCK_CHECKSUM=TRUE)
ub2 chkval_kcbh @16 0x9107 <<<<< Optional block checksum (if DB_BLOCK_CHECKSUM=TRUE)
--可选,如果设置了初始化参数 DB_BLOCK_CHECKSUM,将会启用校验和检查数据块的一致
--可选,如果设置了初始化参数 DB_BLOCK_CHECKSUM,将会启用校验和检查数据块的一致
--另外,数据块的最后 4 字节为块尾(tail),可以配合数据块头来验证数据块的一致性。它的
--另外,数据块的最后 4 字节为块尾(tail),可以配合数据块头来验证数据块的一致性。它的
--结构为:SCN BASE 的 2 位低字节+块类型+序列号
--如果一个块被标识成软损坏,那么其块头的序列号为 0xff,标志为 0x00。
--如果一个块被标识成软损坏,那么其块头的序列号为 0xff,标志为 0x00。
ub2 spare3_kcbh @18 0x0000 <<<<< Not used, filler field
ub2 spare3_kcbh @18 0x0000 <<<<< Not used, filler field
========================================================================================
2、理解ITL Transaction Layer:内部结构名ktbbh。
事务型的数据块(类型为 6)存放表和索引数据,其结构主要由块头、事务层、数据层和块尾 4 部分组成。
其中,事务层由头结构和 ITL(Interested Transaction Slots)构成。 ITL 是一个可变长的数组,
当某个事务修改或准备修改(for update)该块中的行数据时,首先会在 ITL 中寻找一个空闲的插
槽,如果没找到,就动态扩展 ITL,然后在空闲插槽中填写相关的事务信息。事务层头结构从块
偏移 20 开始,其结构 ktbbh 为:
分成两部分,
第一部分 头结构(ktbbh ),为固定长度,长度为24字节,包含事务相关的一些基本信息。
第二部分 ITL (ktbbhitl),可变长度,包含itl,长度根据itl条目的个数变化,每个itl长度为24字节,内部结构名ktbbhitl。
--从偏移量20开始
BBED> p ktbbh
> p ktbbh
ktbbh, 96 bytes @20
ub1 ktbbhtyp @20 0x01 (KDDBTDATA) <<<<< Block type (1=DATA, 2=INDEX)
union ktbbhsid, 4 bytes @24 <<<<< Segment/Object ID
union ktbbhsid, 4 bytes @24 <<<<< Segment/Object ID
ub4 ktbbhsg1 @24 0x00015839
ub4 ktbbhod1 @24 0x00015839
struct ktbbhcsc, 8 bytes @28 <<<<< 最后清洗 SCN(ktbbhcsc)是该块最后一次执行清洗时的 SCN
struct ktbbhcsc, 8 bytes @28 <<<<< 最后清洗 SCN(ktbbhcsc)是该块最后一次执行清洗时的 SCN
ub4 kscnbas @28 0x800330d0
ub4 kscnbas @28 0x800330d0
ub2 kscnwrp @32 0x0000
ub2 kscnwrp @32 0x0000
sb2 ktbbhict @36 3 <<<<< Number of ITL slots ITL 数(ktbbhict)记录了 ITL 数组的个数
sb2 ktbbhict @36 3 <<<<< Number of ITL slots ITL 数(ktbbhict)记录了 ITL 数组的个数
ub1 ktbbhflg @38 0x32 (NONE) <<<<< 标志(ktbbhflg)由一些位值组合而成(OR 操作),这些位值主要包括
ub1 ktbbhflg @38 0x32 (NONE) <<<<< 标志(ktbbhflg)由一些位值组合而成(OR 操作),这些位值主要包括
--KTBFONFL 0x01 // 块在 Free List 中
--KTBFONFL 0x01 // 块在 Free List 中
--KTBFBSEG 0x10 // 块使用位图管理空闲空间
--KTBFBSEG 0x10 // 块使用位图管理空闲空间
--KTBFEXTHD 0x20 // 支持扩展的事务头
--KTBFEXTHD 0x20 // 支持扩展的事务头
ub1 ktbbhfsl @39 0x00 <<<<< ITL TX freelist slot
ub1 ktbbhfsl @39 0x00 <<<<< ITL TX freelist slot
ub4 ktbbhfnx @40 0x01000160 <<<<< DBA of next block on the freelist
ub4 ktbbhfnx @40 0x01000160 <<<<< DBA of next block on the freelist
struct ktbbhitl[0], 24 bytes @44 <<<<< ITL list index, each ITL takes up 24 bytes
struct ktbbhitl[0], 24 bytes @44 <<<<< ITL list index, each ITL takes up 24 bytes
struct ktbitxid, 8 bytes @44
ub2 kxidusn @44 0xffff <<<<<回滚段(kxidusn)是对应事务所在的回滚段编号。
ub2 kxidusn @44 0xffff <<<<<回滚段(kxidusn)是对应事务所在的回滚段编号。
ub2 kxidslt @46 0x0000 <<<<<插槽号(kxidslt)是对应事务在回滚段事务表中的插槽号
ub2 kxidslt @46 0x0000 <<<<<插槽号(kxidslt)是对应事务在回滚段事务表中的插槽号
ub4 kxidsqn @48 0x00000000 <<<<<UNDO WRAP(kxidsqn)是对应事务在回滚段事务表中的 WRAP 值,它和 前两个字段一起唯一标识了一个事务,相当于事务的主键。
ub4 kxidsqn @48 0x00000000 <<<<<UNDO WRAP(kxidsqn)是对应事务在回滚段事务表中的 WRAP 值,它和 前两个字段一起唯一标识了一个事务,相当于事务的主键。
struct ktbituba, 8 bytes @52 <<<<UNDO 地址(ktbituba)是最后生成的 UNDO 记录的地址,
struct ktbituba, 8 bytes @52 <<<<UNDO 地址(ktbituba)是最后生成的 UNDO 记录的地址,
格式为:UNDO DBA(4 字节) +序列号(2 字节) +记录号(1 字节)
格式为:UNDO DBA(4 字节) +序列号(2 字节) +记录号(1 字节)
ub4 kubadba @52 0x00000000
ub4 kubadba @52 0x00000000
ub2 kubaseq @56 0x0000
ub2 kubaseq @56 0x0000
ub1 kubarec @58 0x00
ub1 kubarec @58 0x00
ub2 ktbitflg @60 0x8000 (KTBFCOM) <<<< 标志(ktbitflg)由两部分组成,
ub2 ktbitflg @60 0x8000 (KTBFCOM) <<<< 标志(ktbitflg)由两部分组成,
高 4 位表示事务的提交状态,低 12 位保存该事务修改的本块的行数,事务的提交状态由一些位值组合而成(OR 操作), 这些位值主要包括:
高 4 位表示事务的提交状态,低 12 位保存该事务修改的本块的行数,事务的提交状态由一些位值组合而成(OR 操作), 这些位值主要包括:
KTBFCOM 0x8000 // 事务已提交
KTBFCOM 0x8000 // 事务已提交
KTBFIBI 0x4000 // 使用 ktbituba 指向的 UNDO 记录回滚可以获得本 ITL 插槽的前映像
KTBFIBI 0x4000 // 使用 ktbituba 指向的 UNDO 记录回滚可以获得本 ITL 插槽的前映像
KTBFUPB 0x2000 // 事务提交 SCN 是个上边界,不一定精确
KTBFUPB 0x2000 // 事务提交 SCN 是个上边界,不一定精确
KTBFTAC 0x1000 // 事务在最后清洗时( ktbbhcsc)尚未提交
KTBFTAC 0x1000 // 事务在最后清洗时( ktbbhcsc)尚未提交
union _ktbitun, 2 bytes @62 <<<<SCN WRAP(_ktbitun):该字段复用,如果事务已提交并完成清洗, 该字段保存事务提交SCN 的 SCN WRAP 部分,否则该字段保存空闲空间预支字节数(Free Space Credit)。
union _ktbitun, 2 bytes @62 <<<<SCN WRAP(_ktbitun):该字段复用,如果事务已提交并完成清洗, 该字段保存事务提交SCN 的 SCN WRAP 部分,否则该字段保存空闲空间预支字节数(Free Space Credit)。
比如,删除一行可以释放 80 B 字节,在事务提交前,这80B 就属于 fsc,只有事务提交后,才能正式返回到空闲空间。
比如,删除一行可以释放 80 B 字节,在事务提交前,这80B 就属于 fsc,只有事务提交后,才能正式返回到空闲空间。
sb2 _ktbitfsc @62 0
sb2 _ktbitfsc @62 0
ub2 _ktbitwrp @62 0x0000
ub2 _ktbitwrp @62 0x0000
ub4 ktbitbas @64 0x80012512 <<<<SCN BASE(ktbitbas):事务提交 SCN 的 SCN BASE 部分。
ub4 ktbitbas @64 0x80012512 <<<<SCN BASE(ktbitbas):事务提交 SCN 的 SCN BASE 部分。
struct ktbbhitl[1], 24 bytes @68
struct ktbitxid, 8 bytes @68
ub2 kxidusn @68 0x000a
ub2 kxidusn @68 0x000a
ub2 kxidslt @70 0x0000
ub2 kxidslt @70 0x0000
ub4 kxidsqn @72 0x000002f5
ub4 kxidsqn @72 0x000002f5
struct ktbituba, 8 bytes @76
ub4 kubadba @76 0x00c002ee
ub4 kubadba @76 0x00c002ee
ub2 kubaseq @80 0x00a1
ub2 kubaseq @80 0x00a1
ub1 kubarec @82 0x1c
ub1 kubarec @82 0x1c
ub2 ktbitflg @84 0x8000 (KTBFCOM)
ub2 ktbitflg @84 0x8000 (KTBFCOM)
union _ktbitun, 2 bytes @86
sb2 _ktbitfsc @86 0
sb2 _ktbitfsc @86 0
ub2 _ktbitwrp @86 0x0000
ub2 _ktbitwrp @86 0x0000
ub4 ktbitbas @88 0x00000000
ub4 ktbitbas @88 0x00000000
struct ktbbhitl[2], 24 bytes @92
struct ktbitxid, 8 bytes @92
ub2 kxidusn @92 0x0000
ub2 kxidusn @92 0x0000
ub2 kxidslt @94 0x0000
ub2 kxidslt @94 0x0000
ub4 kxidsqn @96 0x00000000
ub4 kxidsqn @96 0x00000000
struct ktbituba, 8 bytes @100
ub4 kubadba @100 0x00000000
ub4 kubadba @100 0x00000000
ub2 kubaseq @104 0x0000
ub2 kubaseq @104 0x0000
ub1 kubarec @106 0x00
ub1 kubarec @106 0x00
ub2 ktbitflg @108 0x0000 (NONE)
ub2 ktbitflg @108 0x0000 (NONE)
union _ktbitun, 2 bytes @110
sb2 _ktbitfsc @110 0
sb2 _ktbitfsc @110 0
ub2 _ktbitwrp @110 0x0000
ub2 _ktbitwrp @110 0x0000
ub4 ktbitbas @112 0x00000000
ub4 ktbitbas @112 0x00000000
为什么要设置 INI_TRANS 参数
在创建表或索引时,可以指定 INI_TRANS 参数,该参数定义了表或索引数据块中预留的 ITL插槽数。如果某个事务在 ITL 中没有找到空闲的插槽,就会动态扩展 ITL,这种扩展是从数据块的低端往高端进行的,正好和行数据相反。行数据是从高端往低端分配的,每个 ITL 插槽需要24 B,如果数据块无足够的空闲空间,就会产生等待事件 enq: TX - allocate ITL entry。
当占用 ITL 插槽的某个事务提交或回滚后,释放了 ITL 插槽,正在等待的事务才能继续进行
下去。这种现象一般出现在表上有很多并发事务执行 UPDATE 操作的情况下,解决的办法是增加表及索引的 INI_TRANS 值。默认情况下,表的 INI_TRANS 值是 2,索引的 INI_TRANS 值也是 2,索引自身的维护(节点分裂)是一个内部事务,需要 ITL 插槽,插槽 0 被保留用于索引维护内部事务。增加 INI_TRANS 值有两种方法。
创建表或索引时,指定 INITRANS 值,将对所有的数据块起作用。
表或索引被创建后,修改 INITRANS 值,只对修改后新建的数据块起作用。
========================================================================================
3、理解记录结构 Data Layer:包括Data Header,Table Directory,Row Directory,Free Space和Row Data。
表中的数据以记录或行的形式保存在事务型的数据块 (kcbh.type_kcbh=6 并 且ktbbh.ktbbhtyp=1)中,
它们位于数据块的数据层。表记录的数据层包括头结构、表索引、行索引和行数据。
其中Data Header:长度14字节,内部数据结构名kdbh
头结构在块中的起始位置可以按以下公式计算。
对于 Free List 管理空闲空间(FLM)的数据块: 44+ITLs*24。
对于位图管理空闲空间(ASSM)的数据块: 52+ITLs*24。
///头结构 kdbh 由以下字段组成:
BBED> p kdbh
> p kdbh
kdbh, 14 bytes @124
ub1 kdbhflag @124 0x00 (NONE) <<<<< N=pctfree hit(clusters)
ub1 kdbhflag @124 0x00 (NONE) <<<<< N=pctfree hit(clusters)
<<<<< F=do not put on freelist
<<<<< F=do not put on freelist
<<<<< K=flushable cluster keys
<<<<< K=flushable cluster keys
sb1 kdbhntab @125 1 <<<<表数(kdbhntab)定义了表索引数组的长度。
sb2 kdbhnrow @126 10 <<<<行数
sb2 kdbhnrow @126 10 <<<<行数
sb2 kdbhfrre @128 -1 <<<< 空闲行插槽(kdbhfrre)定义了行索引数组中第一个空闲的插槽号,如果没有空闲的,则为 0xffff
sb2 kdbhfrre @128 -1 <<<< 空闲行插槽(kdbhfrre)定义了行索引数组中第一个空闲的插槽号,如果没有空闲的,则为 0xffff
sb2 kdbhfsbo @130 38 <<<< 起始空间(kdbhfsbo)定义了数据层中空闲空间的起始偏移
sb2 kdbhfsbo @130 38 <<<< 起始空间(kdbhfsbo)定义了数据层中空闲空间的起始偏移
sb2 kdbhfseo @132 7149 <<<< 结束空间(kdbhfseo)定义了数据层中空闲空间的结束偏移
sb2 kdbhfseo @132 7149 <<<< 结束空间(kdbhfseo)定义了数据层中空闲空间的结束偏移
sb2 kdbhavsp @134 7885 <<<< 空闲空间(kdbhavsp)定义了数据层中空闲空间的字节数
sb2 kdbhavsp @134 7885 <<<< 空闲空间(kdbhavsp)定义了数据层中空闲空间的字节数
sb2 kdbhtosp @136 7885 <<<< 最终空闲空间(kdbhtosp)定义了 ITL 中的事务提交后,数据层中空闲空间的字节
sb2 kdbhtosp @136 7885 <<<< 最终空闲空间(kdbhtosp)定义了 ITL 中的事务提交后,数据层中空闲空间的字节
Table Directory:表索引 一般table只有一个条目,cluster则有一个或多个条目。每个条目长4字节,内部数据结构名kdbt。
表索引是一个数组,定义了行数据可能包括的表,由于簇可能包含多个表,这些表在物理存
储上使用同一个段,它们相关的行(拥有相同的簇值)被放在一起,Oracle 在设计数据层的结构
时考虑到了这一点,通过表索引来区分相关的行属于哪一个表。表索引的插槽由4 个字节组成,
其结构kdbt 如下:
BBED> p kdbt
> p kdbt
kdbt[0], 4 bytes @138
sb2 kdbtoffs @138 0 <<<<偏移(kdbtoffs)定义了该表在行索引中的起始插槽号
sb2 kdbtoffs @138 0 <<<<偏移(kdbtoffs)定义了该表在行索引中的起始插槽号
sb2 kdbtnrow @140 10 <<<<行数(kdbtnrow)定义了该表在行索引中使用的插槽数
sb2 kdbtnrow @140 10 <<<<行数(kdbtnrow)定义了该表在行索引中使用的插槽数
每项的含义如下所示。
偏移(kdbtoffs)定义了该表在行索引中的起始插槽号。
行数(kdbtnrow)定义了该表在行索引中使用的插槽数。
对于非簇表,表索引只有一个插槽,而对于簇表,表索引可能有多个插槽,每个插槽对应簇中的一个表,对应关系为:插槽号=obj$表中的tab#列。
正因为如此,即使簇中的某个表没有对应的记录,在表索引中,也需要为它留一个插槽,行数为0。
Row Directory:行索引 数目由块中数据的行数决定,每个条目长2字节,内部数据结构名kdbr
行索引也是一个数组,定义了该块中包含的所有行数据的位置。行索引的插槽由2 个字节组
成,其结构kdbr 如下:
BBED> p kdbr
> p kdbr
sb2 kdbr[0] @142 7149
kdbr[0] @142 7149
sb2 kdbr[1] @144 8038
kdbr[1] @144 8038
sb2 kdbr[2] @146 7175
kdbr[2] @146 7175
sb2 kdbr[3] @148 7186
kdbr[3] @148 7186
sb2 kdbr[4] @150 8001
kdbr[4] @150 8001
sb2 kdbr[5] @152 7275
kdbr[5] @152 7275
sb2 kdbr[6] @154 7392
kdbr[6] @154 7392
sb2 kdbr[7] @156 7415
kdbr[7] @156 7415
sb2 kdbr[8] @158 7938
kdbr[8] @158 7938
sb2 kdbr[9] @160 7925
kdbr[9] @160 7925
偏移定义了该行数据在数据层中的偏移字节。在计算该行数据在块中的偏移值时,还要加上数据层自身的偏移值。
行数据由行头和各列值组成,行头的基本结构kdrh 为:
每项的含义如下所示
标志(kdrhflag)由一些位值组合而成(OR 操作),这些位值主要包括:
KDRHFK 0x80 // 簇的键
KDRHFC 0x40 // 簇表成员
KDRHFH 0x20 // 行头
KDRHFD 0x10 // 已删除
KDRHFF 0x08 // 第一个分片
KDRHFL 0x04 // 最后一个分片
KDRHFP 0x02 // 分片中的第一列延续自上一个分片
KDRHFN 0x01 // 分片中的最后一列将在下一分片继续
行锁(kdrhlock)是用修改该行的事务在ITL 中的插槽号来表示的。
列数(kdrhccnt)定义了本行数据包含的列数。
在一般情况下,紧邻行头的就是各个列的数据,其结构为该列数据的长度和实际数据。列的长度为1~3 B,
如果第一个字节为0xff,表示该列为空(NULL);如果第一个字节为0xfe,
那么后两位表示字节的长度,否则第一个字节表示列数据的长度。列在数据行中的顺序一般和表定义中的顺序一致,
但也可能不完全相同,比如,表中的LONG 字段在实际行数据中一般被放在最后,实际的列顺序在col$表的segcol#列中定义。
BBED> p *kdbr[7]
> p *kdbr[7]
rowdata[266]
[266]
------------
ub1 rowdata[266] @7539 0x2c
[266] @7539 0x2c
BBED> x /rnc
> x /rnc
[266] @7539
------------
flag@7539: 0x2c (KDRHFL, KDRHFF, KDRHFH)
: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@7540: 0x00 <<<< 行锁(kdrhlock)是用修改该行的事务在ITL 中的插槽号来表示的
: 0x00 <<<< 行锁(kdrhlock)是用修改该行的事务在ITL 中的插槽号来表示的
cols@7541: 2 <<<< 列数
: 2 <<<< 列数
0[2] @7542: 41
col 1[6] @7545: I_IND1
1[6] @7545: I_IND1
6、freespace
ub1 freespace[7111] @162
7、rowdata
rowdata[915] @7273
8、Tailchk:保存在块结尾用于校验的数据,长度4个字节,内部结构名tailchk。
BBED> p tailchk
> p tailchk
ub4 tailchk @8188 0x30d00601
tailchk @8188 0x30d00601
--tailchk=Lower order two bytes of SCN Base(bas_kcbh) + Block Type(type_kcbh) + SCN Seq(seq_kcbh)
tailchk=Lower order two bytes of SCN Base(bas_kcbh) + Block Type(type_kcbh) + SCN Seq(seq_kcbh)
30d0 +30d0+30d0=30d00601
30d0 +30d0+30d0=30d00601
--块的scn为:SCN= (SCN_WRP * 4294967296) + SCN_BAS
块的scn为:SCN= (SCN_WRP * 4294967296) + SCN_BAS
求scn语句: select to_char(to_number(‘scn’,'xxxxxxxxxx’),’999999999999′) from dual;
求scn语句: select to_char(to_number(‘scn’,'xxxxxxxxxx’),’999999999999′) from dual;
#dba 求文件号、块号
set serveroutput on
declare
p_dba VARCHAR2 (255) :='0x00800212';
l_str VARCHAR2 (255) DEFAULT NULL;
BEGIN
l_str :=
'datafile# is:'
|| DBMS_UTILITY.data_block_address_file (TO_NUMBER (LTRIM (p_dba, '0x'),'xxxxxxxx'))
|| chr(10)||'datablock is:'
|| DBMS_UTILITY.data_block_address_block (TO_NUMBER (LTRIM (p_dba, '0x'),'xxxxxxxx'));
dbms_output.put_line(l_str);
END;
===or
select dbms_utility.data_block_address_file(12583052) "file",dbms_utility.data_block_address_block(12583052) "block" from dual;
4、解析Oracle 字段的内部数据存储格式