深入解析Oracle数据块的内部结构

访问www.tomcoding.com网站,学习Oracle内部数据结构,详细文档说明,下载Oracle的exp/imp,DUL,logminer,ASM工具的源代码,学习高技术含量的内容。

在Oracle数据库的存储体系中,数据块是整个体系的最小逻辑单元,也是I/O操作的基本单位。理解数据块的内部结构,不仅能够帮助DBA排查数据损坏、空间分配异常等底层问题,更能让开发者从根本上优化数据库的存储与访问性能。

Oracle数据块是分层结构,从上到下依次是块头,事务固定层,事务可变层,数据头层,表目录层,行目录层,空闲空间,行数据层和块尾。我们从上到下来分析各个层的结构。

1. 块头(Block Header)

块头是数据块最外层的元数据区域,存储整个块的基础控制信息,主要用于在SGA的缓存中识别不同的数据块。包含数据块的类型,数据块的地址(RDBA),块的系统改变号(SCN)和块的校验和等内容。一个块头的dump信息如下。

buffer tsn: 9 rdba: 0x02000087 (8/135)

scn: 0x0000.003f2481 seq: 0x01 flg: 0x06 tail: 0x24810601

frmt: 0x02 chkval: 0x70f9 type: 0x06=trans data

2. 事务固定层(Tansaction Layer Fixed)

这一次包含了块的事务信息中的固定部分,包含了段内的对象ID(segment object id),事务槽的个数,管理这个块的块地址(BDBA),块内的数据类型等。这部分的dump信息如下。

Block header dump: 0x02000087

Object id on Block? Y

seg/obj: 0x1338d csc: 0x00.3f2480 itc: 2 flg: E typ: 1 - DATA

brn: 0 bdba: 0x2000080 ver: 0x01 opc: 0

inc: 0 exflg: 0

其中事务槽的个数叫做itc,在这里是2,这个值决定了事务可变层中ITL的个数。

3. 事务可变层(Transaction Layer Variable)

这一层就是ITL(Interested Transaction List):也叫事务槽,每个槽位占用24字节,记录当前块上所有未提交事务的信息,用于实现多版本并发控制与行锁管理,ITL的个数在上一次中,由itc变量控制。事务槽的dump信息如下。

Itl Xid Uba Flag Lck Scn/Fsc

0x01 0x0009.01c.00000d6b 0x00c010d0.0309.2c --U- 1 fsc 0x0000.003f2481

0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000

4. 数据头层(Data Header Layer)

数据头是定义块中数据信息的结构,比如块中包含了多少个表的数据(ntab),块中一共包含了多少条数据(nrow),数据空闲空间的偏移量(fsbo),总共的空闲空间大小(tosp)等等。数据头的dump信息如下。

data_block_dump,data header at 0x2b57aace6a64

===============

tsiz: 0x1f98

hsiz: 0x14

pbl: 0x2b57aace6a64

76543210

flag=--------

ntab=1

nrow=1

frre=-1

fsbo=0x14

fseo=0x1f4c

avsp=0x1f38

tosp=0x1f38

5. 表目录层(Table Directory Layer)

这是一个数组结构,数据块中包含了几个表的数据,这个数组就有几个元素,普通表的数据块中只包含一个表,所有这里只有一个数组元素,Cluster表的数据块中可能包含几个表的数据,所以就会有好几个数组元素,数组的下标就是表的编号。这个结构有两个字段,分别叫做nrow和offs,表示表在块中包含的数据条数和表数据在下面的行目录中开始的位置。它的dump信息如下。

0xe:pti0 nrow=1 offs=0

表示块中只有一个表的数据,数据条数是1,从行目录的第0个元素开始计算。

6. 行目录(Row Directory Layer)

行目录的结构比较简单,其实就是一个2字节的数组,每个数组元素中存放着一条记录的偏移量,叫做row offset,这个偏移量就是这行数据开始的位置,有多少条数据就有多少个数组元素。这个偏移量有一个相对地址,这个相对地址是数据头的基地址,这一点一定要搞清楚,因为很容易会把这个偏移量看做是相对于块头的地址。所以这个偏移量加上数据头的偏移量才是数据相对于块头的位置。行目录的dump信息如下。

0x1a:pri0 offs=0x1f80

0x1c:pri1 offs=0x1f74

0x1e:pri2 offs=0x1f64

0x20:pri3 offs=0x1f54

7. 空闲空间(Free Space)

行目录是从块头的方向往块尾增长的,每增加一行数据,行目录就增加一个元素。块中的数据是从块尾向块头的方向增长的,每增加一行数据,就向块头方向移动一段位置,所以在行目录和最后的数据行之间就有一段空间,这就是空闲空间,PCTFREE参数决定了空闲空间的大小。

8. 行数据层(Row Data Layer)

行数据位于块的底部,自下而上增长,是真正存储表中实际业务数据的区域。通常情况下一行数据在一个块中由一个数据片组成,在行链接的情况下单行数据可以跨多个数据块存储,由多个数据片组成,每个数据片在一个块中。每一个数据片的存储结构分为:行头(Row Header)和列数据。行头一般有三个字节,分别是fb,lb和cc。fb是数据片的标志,决定数据行由怎样的数据片组成。lb是锁标志,如果不为0,则表示这行数据对应着块中ITL的哪个槽位。cc则表示数据片中包含几列数据。列数据由数据长度和数据值组成,不同类型的列有不同格式的数据表示形式。数据行的dump信息如下。

tab 0, row 0, @0x1f4c

tl: 76 fb: --H-FL-- lb: 0x1 cc: 5

col 0: 2 c1 02

col 1: 30

31 61 61 61 61 61 61 61 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20

20 20 20 20 20

col 2: 10 31 62 62 62 62 62 62 62 62 62

col 3: 12 31 63 63 63 63 63 63 63 63 63 63 63

col 4: 14 31 64 64 64 64 64 64 64 64 64 64 64 64 64

9. 块尾(Block Tail)

数据块的块尾由4个字节组成,用于块的校验。在前面的块头dump信息中其实包含了块尾的信息。

buffer tsn: 9 rdba: 0x02000087 (8/135)

scn: 0x0000.003f2481 seq: 0x01 flg: 0x06 tail: 0x24810601

frmt: 0x02 chkval: 0x70f9 type: 0x06=trans data

相关推荐
pixcarp11 小时前
知识库系统的内容资产闭环怎么设计
服务器·数据库·后端·golang
JosieBook11 小时前
【数据库】时序预测能力的分级进化:TimechoAI如何让每一类用户都能精准预见未来
java·开发语言·数据库
吴声子夜歌13 小时前
SQL经典实例——使用多张表
数据库·sql
倔强的石头_14 小时前
《Kingbase护城河》——深度解密数据库行锁冲突与等待事件架构
数据库
IT策士14 小时前
Redis 从入门到精通:性能调优与多语言客户端对比
数据库·redis·缓存
Bert.Cai15 小时前
Oracle INSTR函数详解
数据库·oracle
茉莉玫瑰花茶17 小时前
综合案例 - AI 智能租房助手 [ 5 ]
服务器·数据库·人工智能·python·ai
ywl47081208717 小时前
jwt生产token,简单版helloworld
java·数据库·spring
器灵科技17 小时前
AI视频工具实测:Seedance/可灵/HappyHorse谁最能打?
java·运维·数据库·人工智能·github