【数据库设计与实现】第1章:空间管理与数据布局

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 空间管理与数据布局 设计原则数据库设计数据布局和空间管理应当考虑哪些因素呢?又有哪些设计原则?本章先提出问题,看有哪些因素要考虑,然后选取Oracle和MySQL这2款最流行的数据库,看看它们是如何进行空间管理的。我们先看看有哪些因素要考虑:数据最终要反映到持久设备上,空间管理首先要考虑持久设备(如磁盘)的物理特性,考虑如何组织数据才能最大化地发挥存储设备的效率;如何协调平衡多样化的数据,如超大的
空间管理与数据布局  
设计原则

数据库设计数据布局和空间管理应当考虑哪些因素呢?又有哪些设计原则?本章先提出问题,看有哪些因素要考虑,然后选取OracleMySQL2款最流行的数据库,看看它们是如何进行空间管理的。我们先看看有哪些因素要考虑:

  • 数据最终要反映到持久设备上,空间管理首先要考虑持久设备(如磁盘)的物理特性,考虑如何组织数据才能最大化地发挥存储设备的效率;
  • 如何协调平衡多样化的数据,如超大的单表和数据庞大的小表,持久数据和临时数据,系统管理数据和用户数据,索引数据和非索引数据等等;
  • 如何平衡数据的逻辑相关性和逻辑独立性,逻辑相关性要求将逻辑上相关的数据聚集在一起,提高联合访问的效率,而逻辑独立性又要求将逻辑上独立的数据独立存放,提高数据失效、迁移、变更的效率;
  • 如何平衡并发度和空间利用率,并发度要求尽可能将所有相关的持久化设备都调动起来,将设备能力尽可能均衡地用满,而空间利用率则要求尽可能紧凑地利用空间,避免空间区域和碎片,提高扫描效率;
Oracle 设计原理
Datafile 空间管理

Oracletablespace由若干个datafile组成,datafileextent为单位进行空间的申请和释放。可以这么说,datafile是空间的提供者,而segment是空间的使用者,两者之间的交互语言就是extentblock

图1.2-1 Block结构

 

表1.2-1 Cache Layer结构

长度

含义

type

1

Block的类型,可以取值:

  • 0x01 undo segment header
  • 0x02 undo block
  • 0x03 save undo header block
  • 0x04 save undo data block
  • 0x05 data segment header block(temp, index, data)
  • 0x06 KTB managed data block(with ITL)
  • 0x07 temp table data block(no ITL)
  • 0x08 sort key
  • 0x09 sort run
  • 0x0a segment free list block
  • 0x0b data file header
  • 0x0c data segment header with FLG blcks
  • 0x0e unlimited undo segment header
  • 0x0f unlimited save undo segment header
  • 0x10 unlimited data segment header
  • 0x11 unlimited data segment header with FLG blocks
  • 0x12 extent map block
  • 0x17 bitmapped segment header
  • 0x1d KTFB bitmapped file space header
  • 0x1e KTFB bitmapped file space bitmap
  • 0x20 first level bitmap block
  • 0x21 second level bitmap block
  • 0x22 third level bitmap block
  • 0x23 pagetable segment header block
  • 0x24 pagetable extent map block
  • 0x25 system managed undo extent map block

frmt

1

格式,标识不同的block版本

spare1/2

2

保留

rdba

4

相对block地址,前10bit为相对文件id,后22bitblock号,可见1tablespace可以有1023datafile,每个datafile可以有4Mblock

scn

6

block最近一次更新时的scn

seq

1

如果更新本blockscn相同,则seq1

flg

1

组合标志位:

  • 0x01  block data 部分为空;
  • 0x02 delayed logging change advance SCN/SEQ
  • 0x04  校验 CHECKSUM
  • 0x08  临时 block

chkval

2

flgCHECKSUM标志为真时,写入前对block计算CHECKSUM,并填入本域,后继读出时会再次计算并检查,防止块损坏

spare3

2

保留

表1.2-2 footer结构

长度

含义

seq

1

等于cache layer中的seq

type

1

等于cache layer中的type

filter

2

数据文件:等于cache layerscn的末尾2byte

控制文件:control seq

block是数据管理的基本单元,在讨论datafile空间管理方式之前,我们先讨论一下block。如图1.2-1所示,所有的block都有3个部分组成:

  • Cache layer :定义 block 的总体信息,详情如表 1.2-1 所示;
  • Data block 中存放的内容,具体内容随 cache layer 中的 type 不同而不同;
  • Footer :如果 block 发生了更改, scn seq 至少有一个会变动,通过比较 footer cache layer 中的对应部分就可以检测块损坏(如写入磁盘时,写入一半掉电的情况),当然 cache layer 中还有 chkval ,如果启用可以提供更强的校验能力;

图1.2-2 datafile文件结构

 

了解了block基本文件结构之后,我们开始讨论datafile是如何提供空间的。如图1.2-2所示,datafileData File HeaderKTFB Bitmapped File Space HeaderKTFB Bitmapped File Space BitmapData组成,其中Data File HeaderKTFB Bitmapped File Space HeaderKTFB Bitmapped File Space Bitmap为文件保留区,保留区占用的block数随db_block_size的变化而变化(2KB保留32block4KB保留16block8KB保留8block16KB32KB保留4block),下面详细看下各个部分的含义:

  • Data File Header :描述本 datafile 的总体信息, Cache Layer.type=0x0b block size 8KB 时占用 2 block ,详情见表 1.2-3
  • KTFB Bitmapped File Space Header :描述 bitmap 的总体信息, Cache Layer.type=0x1d block size 8KB 时占用 1 block ,详情见表 1.2-4
  • KTFB Bitmapped File Space Bitmap :完整的 bitmap ,用于描述本 datafile 中各个 extent 的详细情况, Cache Layer.type=0x1e block size 8KB 时占用 5 block ,详情见表 1.2-5
  • Data :用于存放具体数据;

表1.2-3 Data File Header部分关键信息

含义

dbid

本文件归属的db id

dbname

本文件归属的db name

tablespace

本文件归属的tablespace

file number

本文件的文件编号(dbauba等地址中都会含文件编号)

prev file

归属于同1tablepace的前1datafile

file size

本文件的大小

file type

本文件的类型,3表示数据文件

blksize

block的大小

checkpoint

checkpoint系统信息

backup

backup系统信息

表1.2-4 KTFB Bitmapped File Space Header部分关键信息

含义

RelFno

相对文件编号

Unit

单元数,即bitmap中每个bit位代表的block

Size

datafile包含的block

AutoExtent

对应于create tablespace语法

MaxSize

对应于create tablespace语法

tail

本文件最后1block

first

本文件第一个处于free状态的unit地址

free

free状态的unit数量

表1.2-5 KTFB Bitmapped File Space Bitmap部分关键信息

含义

beginblock

存放datablock地址,前面的区域存放Data File   Header、KTFB Bitmapped File Space Header、KTFB Bitmapped File Space Bitmap

flag

0永久文件,1临时文件

first

block中第1个可用的unit位置

free

blockfreeunit数量

map

1bit代表1unit0表示free1表示used

KTFB Bitmapped File Space Bitmap Block中,对于统一尺寸的extent来说,unit等于extent,即1bit位代表1extent。对于自动管理来说,extent的大小是变化的,1bit位代表1个最小尺寸的extent。由于大extent一定是小extent的整数倍,所以unit将最小exent作为基准,即1bit位代表64K。当extent的实际大小是1M8M64M时就用多个bit位来表示,如1Mextent就用连续的16bit来标识。

从空间利用率来看,由于某个extent只能属于某个特定的segment,所以小extent空间利用率高,大extent空间利用率低。例如当extent的大小为64M时,表哪怕仅使用了1个字节,也为它分配164Mextent,这64MB空间完全属于这个表,其它表无法使用。从性能的角度来看,大的extent空间比较连续,非常适合全表扫描类操作。Oracle的动态管理方式在空间利用率、性能之间做了平衡。

Segment 空间机制

图1.2-3 segment 3级bitmap管理机制

 

通过上节我们知道,datafile是通过bitmap管理表空间的extent分配情况。segment作为实际使用者,需要更加精确地知道本segment中各block的使用情况。如图1.2-3所示,segment是通过3级位图机制对block进行精细化管理的:

  • L1 BMB BitMap Block ):详细描述了其管理的各 data block 的空间使用情况,并有指向其归属的 L2 BMB 指针,详细情况见表 1.2-6
  • L2 BMB :记录了其管理的所有 L1 BMB 地址,并有指向其归属的 L3 BMB 指针,详细情况见表 1.2-7
  • L3 BMB :记录了其管理的所有 L2 BMB 地址,并有指向其归属的 segment header block 指针,实际上 segment header block 本身就是一个特殊的 L3 BMB

表1.2-6 L1 BMB部分关键信息

一级域

二级域

含义

parent dba

其归属的L2 BMB地址

unformatted

未格式化的block数量

total

MAPblock总数

first useful block

MAP中第1个可用的block

MAP(*n)

offset

extent的地址,即extent中首个block的地址

length

extentblock的数量

bits

标识extent中各个block的状态,每个block的状态占用4bit位:

  • 0000 unformatted ,尚未格式化;
  • 0001 full ,已满;
  • 0010 <25% ,空闲空间 <25%
  • 0011 25-50% ,空闲空间 25-50%
  • 0100 50-75% ,空闲空间 50-75%
  • 0101 >75 ,空闲空间 >75%
  • 0110 metadata ,元数据 block segment header block BMB 都是 metadata block

表1.2-7 L2 BMB部分关键信息

一级域

二级域

含义

parent dba

其归属的L3 BMB地址或segment   header block地址

number

MAPL1 BMB的数量

nfree

MAP中尚有空闲空间的L1 BMB数量

ffree

MAP中已满的L1 BMB数量

MAP(*n)

dba

L1 BMB的地址

free

5:空闲;

0FULL

随着申请的data block越来越多,需要不断地申请L1 BMBL2 BMBL3 BMB进行管理。实际上,通过L1 BMBL2 BMB已经能够管理非常庞大的data block数量,使用L3 BMB的情况非常少见(当然data segment header block本身就是一个特殊的L3 BMB)。在高并发时,存在多个L1 BMB可用,分散了争用,提高了并发性,可以获得非常高的性能:

  • 通过 data segment header block 找到第 1 个含空闲空间的 L2 BMB L2 Hint for inserts );
  • 对操作进程 PID HASH 运算,得到随机数 N ,在 L2 BMB 中找到第 N L1 BMB;
  • 对操作进程 PID HASH 运算,得到随机数 M ,在 L1 BMB 中找到第 M 个有空闲空间的 data block;
  • 向找到的 data block 插入数据;

实际插入算法更加复杂,既要考虑一定的随机性和离散性,避免并发插入在特定的data blockBMB上竞争,又要考虑一定的聚集性,提高空间利用率和数据扫描效率(实际上会优先插入HWM以下的data block),最终算法在两者之间进行平衡。

图1.2-4 data segment header block结构

 

表1.2-8 Extent Control Header部分关键信息

一级域

二级域

含义

extents

segmentextent数量

blocks

segmentblock数量(不含segment header block

High HWM

HWM

High HWM的地址

ext

High HWM在哪个extent

blk

High HWM在该extent的哪个bock

ext size

High HWM所在的extent有多大

blocks below

segment中处于High   HWM下的block数量

Low HWM

HWM

Low HWM的地址

ext

Low HWM在哪个extent

blk

Low HWM在该extent的哪个bock

ext size

Low HWM所在的extent有多大

blocks below

segment中处于Low HWM下的block数量

L1 BMB for high HWM block

High HWM所在的block归属的L1 BMB

L1 BMB for low HWM block

Low HWM所在的block归属的L1 BMB

nl2

segmentL2 BMB的数量

blksz

block的大小

L2 array start offset

L2 Bitmap Mapsegment header block中的偏移

First level3 BMB

L3 BMB链表头

Last level3 BMB

L3 BMB链表尾

L2 hint for inserts

从本L2 BMB开始查找空闲空间供插入

Last level2 BMB

最新的L2 BMB

Last level1 BMB

最新的L1 BMB

表1.2-9 Extent Map和Auxiliary Map部分关键信息

一级域

二级域

含义

next

下一个map block的地址,随着extent数量的不断增长,data segment header block中就不够存放,这时会申请独立的maptype=0x12   extent map block)存放多出来的map

extents

extent的数量

Extent Map(*n)

dba

extent的地址

length

extentblock数量

Auxiliary Map(*n)

extent index

数组下标,虚拟列

L1 dba

管理该extentL1 BMB地址,1L1 BMB可以管理多个extent1extent只能归属于1L1 BMB管理

data dba

extent中首个data   block的地址,extent中可能有L1 BMBL2 BMBL3 BMBExtent   Map BlockSegment Header Block等等,这些Metadata Block一般处于extent的头部

如图1.2-4所示,data segment header block包含如下几个关键部分:

  • 通过 extent control header L3 BMB L2 BMB L1 BMB 就可以知道所有 data block 的空间使用情况、 HWM 情况,然后进行高并发的插入操作;
  • 通过 extent control header extent map auxiliary map 就可以知道所有数据的分布情况、 HWM 情况,进行高效的数据扫描,即从 extent map 起始 extent 开始扫描,扫描至 Low HWM ,对于 Low HWM high HWM 之间的 block ,需要参考 L1 BMB ,以避开尚未格式化的 block

图1.2-5 extent内block分布示例

 

最后再看一下extent内的block分布情况,不管block是何种类型,最终都要落到extent内,接受以extent为单位的连续空间管理。图1.2-5给出了extentblock的分布示例,如果extent内存在metadata类型的block,一般都存放在extent的头部。extent在使用和分配上存在如下规律:

  • 延迟分配,建表时不分配 extent ,只有在实际插入数据时才会分配 extent
  • 非统一大小时, extent 的大小是动态变化的(以 block size 等于 8K 为例):
    • 0-15 extent ,每个 extent 包括 8 block ,此时 segment 总大小 <=1M ,每个 L1 BMB 可以管理 16 block
    • 16-79 extent ,每个 extent 包括 128 block ,此时 segment 总大小 <=32M ,每个 L1 BMB 可以管理 64 block
    • 80-199 extent ,每个 extent 包括 1024 block ,此时 segment 总大小 <=1G ,每个 L1 BMB 可以管理 256 block
    • >199 extent ,每个 extent 包括 8192 block ,此时 segment 总大小 >1G ,每个 L1 BMB 可以管理 1024 block
  • 有些情况下 1 L1 BMB 会管理多个 extent ,所以有的 extent 中没有 L1 BMB ,有些情况下 1 L1 BMB 无法将单个 extent 中的所有 block 都管理起来,此时 extent 中就会有多个 L1 BMB
  • tablespace 由多个 datafile 组成时, extent 分片会考虑一定的均衡性, segment 会分布在多个 datafile 中,但单个 extent 不会跨 datafile
Data Block 空间机制

图1.2-6 data block结构

 

表1.2-10 Table Directory部分关键信息

长度

含义

flag

1

N=pctfree hit(clusters)

F=don’t put on free list

K=flushable cluster keys

ntab

1

data block涉及的table数,只有clusters才可能大于1

nrow

2

data block中的记录数

frre

2

空闲行的位置,初始为0-1表示满了

fsbo

2

Free space的起始偏移

fseo

2

Free space的结尾偏移

avsp

2

Data block中空闲空间大小

tosp

2

所有事务提交后总可用空间大小

表1.2-11 Row Directory部分关键信息

长度

含义

offs

1

clusters表时有效

nrow

1

1个表的行数

rowoff*n

2

Array,每行记录占1个位置,记录改行记录在Row Data中位置。记录在Row   Directory中的下标是RowID组成部分之一

RowId=Seg/Obj Number + File Number + Block Number + Row Number,其中Row Number就是Row   Directory中的下标

表1.2-10 Row Data部分关键信息

长度

含义

fb

1

K=cluster key

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

  • 删除行时并不立刻删除,而是打上 D 标签,延后删除;
  • 行链接、行迁移,所以需要 H/F/L/P/N 等标签;

lb

1

本行记录被ITL中的哪个事务给锁住了

cc

1

记录的列数,超过255列就需要行链接

data

var

数据,每列数据由length+data组成,length的情况:

  • 0xff 表示 number 类型取值为 null ,没有 data 部分;
  • Length<=250 字节, length 占用 1 个字节;
  • Length>250 字节, length 占用 3 个字节( block 本身的大小不会超过 64K ),再长就采用行链接;

如图1.2-6所示,data block和数据存储强相关的部分主要包括Row DirectoryRow DataOracledata block设计有如下特点:

  • row directory :行目录, array 型结构,每行记录占用 2 个字节,指向该行记录在 Row Data 中的位置。 array 的下标是 RowID 的组成部分,所以某行记录一旦落到 block 中,其在 row directory 中的位置就不能改变( row data 是可以被整理的),因为 index 、行迁移、行链接等都是通过 RowID 来定位的;
  • row data :每行记录的头部大小应尽可能地小,从而提高空间利用率。 fb lb cc 仅占用 3 个字节,每列的 length 部分也是变长的,且对于取值为 null number 类型列,直接通过 length=0xff 来表示,不再占用 data 空间;
  • 随着行记录的增加, row directory 从上向下增长, row data 从下向上增长;
  • data block 如果写入过满,将来 update 操作很可能产生较多行迁移,影响查询性能,为此通过 PCTFree 参数定义插入时预留多少空间出来,用于将来的 update pctfree data block ,以及 B 树的 leaf block 有效,但对 B 树的 root block branch block 无效);
数据布局

Oracle中有system tablesapcesysaux tablespacetemporary tablespaceundo tablespacepermanent tablespace,其存放的数据分别如下:

  • system tablespace :存放数据字典;
  • sysaux tablespace :存放工具相关对象信息;
  • temporary tablespace :存放临时数据,以及在内存不足时作为诸多活动的辅助空间(如排序);
  • undo tablespace :存放 undo 日志(前像);
  • permanent tablespace :存放用户数据;

应用可以根据实际情况创建多个temporary tablespaceundo tablespacepermanent tablespace。同时还可以设置bigfile属性,以容纳更大的数据量。每个tablespace都按照segment进行管理,规则如下:

  • 1 个表创建 1 segment ,如果是分区,每个分区创建 1 segment
  • 1 个索引创建 1 segment ,如果是分区索引,每个分区索引创建 1 segment
  • 表的每个 CLOB BLOB 或者 NCLOB 列都会创建 1 segment ,如果这些列上有索引,还会创建对应的 LOB 索引 segment
MySQL 设计原理
Datafile 空间管理

MySQL同样也采用了tablespacesegmentextentpage(对应oracle中的block)这几个概念,tablespace由若干个datafile组成,datafileextent为单位进行空间的申请和释放。不同的是MySQLextent分成了2种:

  • extent :正常的 extent 1 extent 大小为 1M ,由连续的 page 组成, segment extent 为单位申请和释放空间;
  • frag extent :特殊的 extent 1 frag extent 也是连续的 1M 空间,但是 frag extent 不属于任何 segment ,而是为大家共用。 MySQL 不支持变长 extent ,为了节约空间,每个 segment 的前 32 page frag extent 中申请 page ,超过 32 page 再以 extent 为单位申请空间;

图1.3-1 page结构

 

表1.3-1 FIL HEADER结构

长度

含义

FIL_PAGE_SPACE_OR_CHKSUM

4

4.0版本前存space id,之后存checksum

FIL_PAGE_OFFSET

4

page no

FIL_PAGE_PREV

4

B-Tree叶子page的前1page,用于索引扫描

FIL_PAGE_NEXT

4

B-Tree叶子page的下1page,用于索引扫描

FIL_PAGE_LSN

8

pageLSN,标识本page的最近一次修改

FIL_PAGE_TYPE

2

page类型:

FIL_PAGE_INDEX

FIL_PAGE_UNDO_LOG

FIL_PAGE_INODE

FIL_PAGE_IBUF_FREE_LIST

FIL_PAGE_TYPE_SYS

FIL_PAGE_FIL_FLUSH_LSN

8

  • 系统表空间:刷脏 page ,最近 1 次的 LSN ,本域仅在数据文件的第 1 page 中有效,用于判断数据库是否正常关闭;
  • 用户表空间:未使用;

FIL_PAGE_SPACE_ID

4

pagespace id

表1.3-2 FIL TAILER结构

长度

含义

FIL_CHECKSUM

4

pagechecksum,用于校验异常page

FIL_PAGE_LSN

4

等于FIL HEADER中的FIL_PAGE_LSN,用于检测page写一半系统掉电的异常情况

pageMySQL datafile空间管理的基本单位,其结构如1.3-1所示,组成部分如下:

  • FIL HEADER page 头,定义了 page 的总体信息,详细情况见表 1.3-1
  • Data :数据部分,格式随着 FIL_PAGE_TYPE 不同而不同;
  • FIL TAILER page 尾,用于校验异常 page ,详细情况见表 1.3-2

图1.3-2 datafile总体空间布局

 

了解page的结构,下面看总体空间布局。如图1.3-2所示,MySQL数据文件空间布局相对比较固定,非常有规律可循:

  • FIL_PAGE_TYPE_XDES :该类 page 存放 extent 的管理信息,当 page size 确定后每个 FIL_PAGE_TYPE_XDES page 可以管理的 extent 数量是固定的,这样本 page 就可以按照管理的 extent 数有规律地存放。图 1.3-2 示例是 page size 16K 的情况,每个 FIL_PAGE_TYPE_XDES page 可以管理 256 extent ,每个 extent 包含 64 page ,所以 FIL_PAGE_TYPE_XDES page 每隔 16384 256*64 )个 page 出现 1 个;
  • FIL_PAGE_TYPE_HDR FIL_PAGE_TYPE_HDR FIL_PAGE_TYPE_XDES 非常类似,除了存放 extent 管理信息之外,还多了一个 SPACE HEADER 结构,作为空间管理的总入口,可以这么说, FIL_PAGE_TYPE_HDR 是一个特殊的 FIL_PAGE_TYPE_XDES 。本类 page 只有 1 个,且固定在第 0 个位置上;
  • FIL_PAGE_IBUF_BITMAP :本类 page 存放每个 page 的空闲情况以及 IBUF 的使用情况,由于 FIL_PAGE_IBUF_BITMAP FIL_PAGE_TYPE_XDES 管理的规模一样多,所以 FIL_PAGE_IBUF_BITMAP page 永远跟在 FIL_PAGE_TYPE_XDES page 后面,位置固定;
  • FIL_PAGE_INODE :本类 page 存放各 segment 的入口信息, page 的类型为 FIL_PAGE_INODE ,位置不固定;

图1.3-3 FIL_PAGE_TYPE_HDR vs FIL_PAGE_TYPE_XDES

 

表1.3-3 XDES Entry结构

长度

含义

XDES_ID

8

其归属的segment id

FLST_PREV

6

链表指针,指向前1XDES   Entry,前4个字节为该Entrypage no,后2个字节为page内偏移

FLST_NEXT

6

链表指针,指向后1XDES   Entry,前4个字节为该Entrypage no,后2个字节为page内偏移

XDES_XSTATE

4

表示本XDES Entry处在哪个链表上:

  • XDES_FREE FREE 链表;
  • XDES_FREE_FRAG FREE_FRAG 链表;
  • XDES_FULL_FRAG FULL_FRAG 链表;
  • XDES_FSEG :归属于 XDES_ID 记录的 segment

XDES_BITMAP

16

16*8,共计128bit位,每2bit位对应1page1bit标识该page是否为空(XDES_FREE_BIT),另1bit预留;

表1.3-4 SPACE HEADER结构

长度

含义

FSP_SPACE_ID

4

space id

FSP_NOT_USED

4

保留

FSP_SIZE

4

tablespacepage总数,自动扩展时会不断增加

FSP_FREE_LIMIT

4

小于本数的page都尚未初始化,该数以后的page都尚未加入到FREE LIST

FSP_SPACE_FLAGS

4

32bit位,各位的含义如下:

  • FSP_FLAGS_POS_ZIP_SSIZE :压缩 page size 0 表示非压缩;
  • FSP_FLAGS_POS_ATOMIC_BLOBS :行格式, compressed 或者 dynamic
  • FSP_FLAGS_POS_PAGE_SSIZE page size
  • FSP_FLAGS_POS_DATA_DIR :如果创建表空间显式指定了 data_dir ,设置本 flag
  • FSP_FLAGS_POS_SHARED :是否是共享的表空间;
  • FSP_FLAGS_POS_TEMPORARY :是否是临时表空间;
  • FSP_FLAGS_POS_ENCRYPTION :是否是加密表空间;
  • FSP_FLAGS_POS_UNUSED :未使用的位;

FSP_FRAG_N_USED

4

FSP_FREE_FRAG链表上已经被使用的page

FSP_FREE

16

链表指针,指向空extent(所有page都为空)链表

FSP_FREE_FRAG

16

链表指针,指向含空闲空间的frag extent链表

FSP_FULL_FRAG

16

链表指针,指向已经用满的frag extent链表

FSP_SEG_ID

8

当前系统最大segment id+1,作为分配segment   id的计数器

FSP_SEG_INODES_FULL

16

链表指针,指向完全用满的inode page链表

FSP_SEG_INODES_FREE

16

链表指针,指向尚有空闲空间的inode page链表

下面详细对比一下FIL_PAGE_TYPE_HDR pageFIL_PAGE_TYPE_XDES page,如图1.3-3所示,两者的结构基本是一样的。FIL_PAGE_TYPE_HDR pageSPACE HEADER结构是有信息的,而FIL_PAGE_TYPE_XDES page的对应位置为空。SPACE HEADER结构存放的是空间管理的总入口信息,所以只需要存在于第0page中。在讨论SPACE HEADER前,先看一下XDES Entry结构。如表1.3-3所示,XDES Entry通过XDES_BITMAP标识其管理的extent中各page的空间状态,FLST_PREVFLST_NEXT双向指针将处于相同状态且归属于同1segmentXDES Entry链接在一起。那么这些链表的头指针在哪里呢?在SPACE HEADER结构中,如表1.3-4所示,SPACE HEADER作为总入口,管理着如下5个重要的链表:

  • FSP_FREE 链表:管理所有空的 extent ,指向状态为 XDES_FREE XDES Entry
  • FSP_FREE_FRAG 链表:管理所有含空闲空间的 frag extent ,指向状态为 XDES_FREE_FRAG XDES Entry
  • FSP_FULL_FRAG 链表:管理所有已经写满的 frag extent ,指向状态为 XDES_FULL_FRAG XDES Entry ,随着 frag extent 的满和不满,对应的 XDES Entry 会在 FSP_FREE_FRAG 链表和 FSP_FULL_FRAG 链表之间移动;
  • FSP_SEG_INODES_FULL FSP_SEG_INODES_FREE 链表:分别管理所有已经写满和尚未写满的 INDOES
  • 链表头结构: FLST_LEN 4 个字节 +FLST_FIRST 6 个字节 +FLST_LAST 6 个字节,共计 16 个字节, FLST_LEN 表示链表长度, FLST_FIRST 指向第 1 个节点( 4 个字节的 page no+2 个字节的 page 内偏移), FLST_LAST 指向最后 1 个节点;

通过FSP_FREE_FRAGFSP_FULL_FRAG链表将所有frag extent管理起来,通过FSP_FREE链表将所有尚未分配给segment的空闲extent管理起来,那么已经分配给segmentextent又是如何管理的呢?实际上,就是通过FSP_SEG_INODES_FULLFSP_SEG_INODES_FREE链表进行间接管理的,我们将在segment机制章节进一步讨论。

图1.3-4 FIL_PAGE_IBUF_BITMAP结构

 

表1.3-5 Change Buffer Bitmap结构

长度

含义

IBUF_BITMAP_FREE

2bit

某个page的空闲情况,0(0bytes)1(512bytes)2(1024bytes)3(2048bytes)

IBUF_BITMAP_BUFFERED

1bit

某个page上是否存在ibuf缓存

IBUF_BITMAP_IBUF

1bit

某个page本身是否是ibuf   BTree的节点

最后再看一下FIL_PAGE_IBUF_BITMAP pageMySQL发明了Insert Buffer机制,并将其进一步通用化为Change Buffer机制。其核心思想是对非唯一的二级索引进行insertdelete时,如果对应的page不在缓存中,不必将该page调度进缓存进行实时操作,而是将insertdelete操作缓存到insert buffer page中,待将来读到该page或者后台purge线程再实施真正的insertdelete操作,从而提高效率。但insert buffer机制存在如下约束和要求:

  • 唯一索引上的 insert 操作不能缓存,因为要做唯一性校验,必须读到真正的 page 才能做唯一性校验;
  • insert buffer 是以 BTree 组织的,缓存的每条记录的主键为 spaceid page no counter ,通过 spaceid page no 记录缓存的操作时针对哪个 page 的,但这就要求 page no 在缓存过程中不能发生变化,这就需要一个机制来及时识别 page no 是否可能发生变化;
  • 还需要一个机制来识别某个 page 上的操作是否有缓存,从而在读到该 page 时,先将缓存的操作 merge 进来,然后再实施真正的读处理;

FIL_PAGE_IBUF_BITMAP page就是为这些目的而设计的,FIL_PAGE_IBUF_BITMAP page固定在FIL_PAGE_TYPE_XDES page后面。如图1.3-4所示,change buffer bitmap中每4bit对应后面的1page8192个字节就可以管理16384page8192*8/4)。如表1.3-5所示,4bit的组成如下:

  • IBUF_BITMAP_FREE :给出某个特定 page 的空闲情况,如果空闲空间过小,会发生 page 分裂, page no 会发生变化,不能缓存,否则可以缓存;
  • IBUF_BITMAP_BUFFERED :标识某个特定 page 上是否做了操作缓存;
  • IBUF_BITMAP_IBUF :标识某个特定 page 本身缓存的一部分;
Segment 空间机制

图1.3-5 FIL_PAGE_INODE page结构

 

表1.3-6 INODE Entry结构

长度

含义

FSEG_ID

8

INODE归属的segment0表示未使用

FSEG_NOT_FULL_N_USED

8

FSEG_NOT_FULL链表上已被使用的page

FSEG_FREE

16

链表头,指向已分配给本segment,但尚未使用的extent链表

FSEG_NOT_FULL

16

链表头,指向属于本segment,但尚未用满的extent链表

FSEG_FULL

16

链表头,指向属于本segment,且已完全用满的extent链表

FSEG_MAGIC_N

4

仅在调试模式下使用

FSEG_FRAG_ADDR

128

32*4,管理32frag page(分布在frag   extent中的page),4个字节记录page no

MySQL是通过INODE Entry管理segment的,每个INODE Entry对应1segment。下面结合存放INODE EntryFIL_PAGE_INODE page一起来讨论。如图1.3-5所示,FIL_PAGE_INODE page包括如下2个部分:

  • FSEG_INODE_PAGE_NODE 12 个字节的双向指针,将相关的 FSEG_INODE_PAGE_NODE page 链接在一起。实际上有 2 FSEG_INODE_PAGE_NODE 链表,就是 FIL_PAGE_TYPE_HDR page 中的 FSP_SEG_INODES_FULL FSP_SEG_INODES_FREE 链表,前者将所有已经写满 INODE Entry FSEG_INODE_PAGE_NODE page 链接在一起,后者将尚未写满 INODE Entry FSEG_INODE_PAGE_NODE page 链接在一起;
  • INODE Entry 1 FSEG_INODE_PAGE_NODE page 中可以存放 n INODE Entry (随 page 的大小变化),每个 INODE Entry 管理 1 个具体的 segment

如表1.3-6所示,INODE Entry管理着1个具体的segment,其中的关键信息如下:

  • FSEG_FREE FSEG_NOT_FULL FSEG_FULL 3 extent 链表的指针头,结合 XDES Entry 结构中的双向指针,把已经分配给本 segment extent 按照尚未使用、已使用但尚未用满、已经用满 3 种情况管理起来;
  • FSEG_FRAG_ADDR :通过记录 page 号,将 frag extent 中分配给本 segment 32 page 管理起来;

图1.3-6 空间管理全貌

 

至此,如图1.3-6所示,我们得到MySQL空间管理的全景图(不含ibuf):

  • SPACE HEADER 中的 FSP_FREE 结合 XDES Entry 将所有尚未分配给 segment extent 管理起来;
  • SPACE HEADER 中的 FSP_FREE_FRAG FSP_FULL_FRAG 结合 XDES Entry 将所有尚未用满和已经用满的 frag extent 管理起来;
  • SPACE HEADER 中的 FSP_SEG_INODES_FREE FSP_SEG_INODES_FULL 结合 FSEG_INODE_PAGE_NODE 将所有尚未用满和已经用满的 FIL_PAGE_INODE 管理起来;
  • 每个 segment 1 INODE Entry (存在于 FIL_PAGE_INODE 中),通过 FSEG_FULL FSEG_NOT_FULL FSEG_FREE 结合 XDES Entry 将所有分配给本 segment 的已经用满、尚未用满、尚未使用的 extent 管理起来;
  • frag extent 既被 SPACE HEADER 管理,其中的 page 同时又被 INODE Entry 中的 FSEG_FRAG_ADDR 管理;
Data Page 空间机制

图1.3-7 data page结构

 

表1.3-7 PAGE HEADER结构

长度

含义

PAGE_N_DIR_SLOTS

2

page directory区域的槽位数量

PAGE_HEAP_TOP

2

堆中空闲空间的偏移量

PAGE_N_HEAP

2

堆中记录的数量,包括用户记录、系统记录、标记为删除的记录,同时第1bit位为1时表示记录格式为compact

PAGE_FREE

2

指向第1条标记为删除的记录,记录头有next,可以将所有标记为删除的记录链接在一起

PAGE_GARBAGE

2

标记为删除的记录总空间(行记录的delete flag1),属于可回收的空间

PAGE_LAST_INSERT

2

指向最近1次插入的记录,用于优化顺序插入

PAGE_DIRECTION

2

最后1条记录的插入方向:

  • PAGE_LEFT
  • PAGE_RIGHT
  • PAGE_SAME_REC
  • PAGE_SAME_PAGE
  • PAGE_NO_DIRECTION

标识当前记录的插入顺序,用于插入优化

PAGE_N_RECS

2

以相同方向连续插入记录的数量

PAGE_MAX_TRX_ID

8

page内有效用户记录数,不含系统记录和标记为删除的记录

PAGE_LEVEL

2

当前pageBTree中的层级,叶子节点取值为0

PAGE_INDEX_ID

8

索引id,本page属于哪个索引

表1.3-8 segment info结构

长度

含义

FSEG_HDR_SPACE

4

segment对应的inode   entry所在pagespace id

FSEG_HDR_PAGE_NO

4

segment对应的inode   entry所在pagepage no

FSEG_HDR_OFFSET

2

segment对应的inode   entry在所在page内偏移

如图1.3-7所示,data page除了通用的FIL HEADERFIL TAILER之外,其它关键组成部分如下:

  • PAGE HEADER :描述了本 page 的总体信息,详细见表 1.3-7 ,通过 PAGE_FREE 和每条记录中的 REC_NEXT ,将所有标志为删除的记录链接在一起;
  • SEGMENT INFO :仅在 BTree root page 中设置, SEGMENT INFO1 记录叶子节点 segment 对应的 INODE 信息, SEGMENT INFO2 记录非叶子节点 segment 对应的 INODE 信息;
  • SYS RECORDS 2 条特殊的系统记录, infimum supremun ,占用 26 个字节,用于 MySQL 特有的边界定位和锁控制;
  • USER RECORDS :用户记录,从上向下增长;
  • PAGE DIRECTORY :目录,从下向上增长,每个 slot 占用 2 个字节,指向 USER RECORDS 中的具体某条记录。目录中的 slot 和记录不是一一对应的,每 4 8 条记录在目录中占用 1 slot

有效的用户记录(删除标志位不为真)和2条系统记录通过记录头的REC_NEXT链接在一起,链接的顺序即为索引的键值顺序,且infimum永远是第1条记录,而supremum永远是最后1条记录。为了加快记录匹配效率,MySQLpage的底部设计了DIRECTORY区域,每隔4-8条记录占用1slotslot对应多少条记录是动态变化的,slot之间也不相等,就某个slot来说,通过对应记录头的REC_NEW_N_OWNED记录相应的记录数)。由于DIRECTORY区域是有序的(按主键或索引键逆序存放),可以通过折半查找快速匹配到目标记录。

图1.3-8 compact记录格式

 

表1.3-9 RECORD HEADER结构

长度

含义

REC_NEW_INFO_BITS

4bits

仅使用了前2bit1bit位标记本行记录是否已经被删除,另1bit位标记本行记录是否为BTree当前Level最左边page的第1条用户记录

REC_NEW_N_OWNED

4bits

0表示本行记录在page   directory中占1slot,具体取值为本slot和下1slot之间的记录数

REC_NEW_HEAP_NO

13bits

本行记录在堆中的序号,用于MySQL的锁机制

REC_NEW_STATUS

3bits

记录的类型:

  • REC_STATUS_ORDINARY :叶子节点记录;
  • REC_STATUS_NODE_PTR :非叶子节点记录;
  • REC_STATUS_INFIMUM infimum 系统记录;
  • REC_STATUS_SUPREMUM supremum 系统记录;

REC_NEXT

16btis

指向本page中的下1条记录,用于2中情况:

  • 有效记录:按键值顺序将本 page 内所有有效记录链接在一起;
  • 无效记录:将本 page 内所有标记为删除的记录链接在一起;

compact格式已经成为MySQL的主流格式。如图1.3-8所示,compact记录格式包括如下组成部分:

  • RECORD_HEADER :记录的头部信息,详情如表 1.3-9 所示,记录在 page 内的偏移一般都是指 RECORD HEADER 的位置,因为记录的其它几个部分都是变长的;
  • VAR_COL_LEN_LST :每个变长列的实际长度在此描述,最大长度小于 255 或者实际长度小于 128 1 个字节,否则占 2 个字节;
  • NULL_BITS :每个可为 NULL 的列在此占 1 bit ,如果列的实际值为 NULL ,此 bit 位为真, ROW_DATA 部分不会出现此列;
  • ROW_DATA :实际列数据,聚集索引会增加事务 id 6 个字节)和回滚指针( 7 个字节) 2 个隐藏列;
数据布局

MySQL的数据包括系统数据、临时数据、回滚数据、用户数据、重做数据和binlog数据,重做数据和binlog数据相对独立,和tablespace没有太大关系,下面重点看其它几个数据的布局:

  • 用户数据: InnoDB 的所有表都是索引组织表,每个索引创建 2 segment 1 segment 存放叶子节点 page 1 segment 存放非叶子节点 page 。每张表存放的 tablespace 随着历史的演进有 3 种方案:
    • 早期版本:所有数据都存放在 1 个公共的系统 tablespace 中;
    • 其后版本:增加支持每张表有 1 个独立的 tablespace 中;
    • 近期版本:增加支持通用的 tablespace
  • 系统类数据( InnoDB ):主要有数据字典数据和系统数据,存放在公共的系统 tablespace 中。字典数据表有 SYS_TABLES SYS_INDEXS SYS_COLUMNS SYS_FIELDS ,分别存放表信息、索引信息、表列信息、索引列信息,也采用索引组织表方式存放。系统数据有 insert buf double write 、事务系统数据等等;
  • 临时数据:存放用户创建的临时表,对应临时 tablespace
  • 回滚数据:存放回滚数据,包括 rollback segment undo log segment ,早期版本存放在公共的系统 tablespace 中,近期版本可存放在独立的 undo tablespace 中;
总结与分析

OracleMySQL的空间布局总体上非常类似,采用tablespacesegmentextentblockpage 4层管理机制。extentblockpage)最大化地发挥持久设备的物理特性,tablespacesegment用于在逻辑上平衡数据的独立性和相关性。不过在管理设计上,OracleMySQL还是存在非常大的差异性。

blockpage)层面,Oracleblock设计更加通用,MySQLpage设计与索引组织表深度耦合,具体表现在:

  • 对于单条记录, MySQL 设计了 NULL_BITS ,稀疏场景下可以有效节省空间。不过 MySQL 的记录头和隐藏列比较厚重,每条记录占用 18 个字节( RECORD HEADER 5 个字节,事务 id 6 个字节,回滚指针占 7 个字节), Oracle 的记录头仅占 3 个字节;
  • MySQL page 也设计相对比较粗放,某些区域仅在特定场景下有效,如 SEGMENT INFO 仅在 BTree root page 中有效, FIL_PAGE_PREV FIL_PAGE_NEXT 仅对 BTree 的叶子节点 page 有效等等;
  • Oracle 采用了相对地址管理方式, RowID 中保存了 file no block no directory id ,优势是可以快速定位记录,缺点是 block 内的碎片整理可以比较高效,但 block 间的整理涉及记录在 block 间移动,代价非常高 (shrink table ,调整 rowid ,涉及面较广 ) MySQL 采用的是主键管理方式,数据和索引解耦,优势是不仅可做 page 内的碎片整理,还可以做 page 间的碎片整理( optimize table ),缺点是定位记录需在 BTree 中检索,然后在 page 内通过 directory 进行折半查找,定位效率低;
  • Oracle page 组织方式上,记录之间没有强的依赖关系,插入操作可以并发执行,并发间竞争小。 MySQL 是索引组织的,插入操作竞争 page 的概率大,且对于每个插入操作而言,需要在 directory 中进行这边查找,且有可能发生 directory 目录重组,单次插入操作的平均成本也相对较高;

extent层面,Oracle通过变长extent应对多样化的表大小,MySQL则通过frag extent来达到类似的效果。不过extentblock的管理上,Oracle做得更加精细,也更加准确。采用4bit描述1block,区分<25% free25-50% free50-75% free>75% freeMySQL只使用了1bit(虽然预留了2bit),只能描述1page满还是空。当然MySQL还有1change buffer机制,为了获得好的缓存效果,也统计了page的空间情况,但也只区分了0 free512 free1024 free2048 free,完全针对change buffer机制定制,在两处对page进行了各自的统计,并没有拉通设计。

segment层面,Oracle采用三级位图进行管理,实际上L1 BMB已经达到block级,和extentblock的管理是拉通的。MySQL则通过3个双向链表FSEG_FREEFSEG_NOT_FULLFSEG_FULL1FSEG_FRAG_ADDR位图进行管理。实际上,Oracle刚开始也采用的链表方式管理,然后演进到位图方式。链表管理方式需要从链表头开始进行遍历,高并发下竞争非常明显,影响并发效率。当然MySQL在并发插入时瓶颈在索引组织表上,此处的瓶颈还没有显现出来。

segment的使用上,两者都区分undo segmenttemporary segmentOracle将大字段(BLOB)放在独立的segment中,表数据和索引逻辑独立,所以也分别放在各自的segment中。MySQL是索引组织表,并将索引的叶子节点和非叶子节点分别放在2个不同的segement中。

tablesapce层面,都区分permanent tabletemporary tablespaceundo tablespace,两者没有太大的本质区别。

PDF版下载地址:http://blog.itpub.net/69912723/viewspace-2713926/

相关文章
|
缓存 Oracle 关系型数据库
【数据库设计与实现】第1章:空间管理与数据布局
空间管理与数据布局 设计原则数据库设计数据布局和空间管理应当考虑哪些因素呢?又有哪些设计原则?本章先提出问题,看有哪些因素要考虑,然后选取Oracle和MySQL这2款最流行的数据库,看看它们是如何进行空间管理的。我们先看看有哪些因素要考虑:数据最终要反映到持久设备上,空间管理首先要考虑持久设备(如磁盘)的物理特性,考虑如何组织数据才能最大化地发挥存储设备的效率;如何协调平衡多样化的数据,如超大的
【数据库设计与实现】第1章:空间管理与数据布局
|
算法 流计算
【最优潮流】二阶锥松弛在配电网最优潮流计算中的应用(Matlab代码实现)
【最优潮流】二阶锥松弛在配电网最优潮流计算中的应用(Matlab代码实现)
【最优潮流】二阶锥松弛在配电网最优潮流计算中的应用(Matlab代码实现)
|
7天前
|
人工智能 自动驾驶 大数据
预告 | 阿里云邀您参加2024中国生成式AI大会上海站,马上报名
大会以“智能跃进 创造无限”为主题,设置主会场峰会、分会场研讨会及展览区,聚焦大模型、AI Infra等热点议题。阿里云智算集群产品解决方案负责人丛培岩将出席并发表《高性能智算集群设计思考与实践》主题演讲。观众报名现已开放。
|
24天前
|
存储 人工智能 弹性计算
阿里云弹性计算_加速计算专场精华概览 | 2024云栖大会回顾
2024年9月19-21日,2024云栖大会在杭州云栖小镇举行,阿里云智能集团资深技术专家、异构计算产品技术负责人王超等多位产品、技术专家,共同带来了题为《AI Infra的前沿技术与应用实践》的专场session。本次专场重点介绍了阿里云AI Infra 产品架构与技术能力,及用户如何使用阿里云灵骏产品进行AI大模型开发、训练和应用。围绕当下大模型训练和推理的技术难点,专家们分享了如何在阿里云上实现稳定、高效、经济的大模型训练,并通过多个客户案例展示了云上大模型训练的显著优势。
|
27天前
|
存储 人工智能 调度
阿里云吴结生:高性能计算持续创新,响应数据+AI时代的多元化负载需求
在数字化转型的大潮中,每家公司都在积极探索如何利用数据驱动业务增长,而AI技术的快速发展更是加速了这一进程。
|
18天前
|
并行计算 前端开发 物联网
全网首发!真·从0到1!万字长文带你入门Qwen2.5-Coder——介绍、体验、本地部署及简单微调
2024年11月12日,阿里云通义大模型团队正式开源通义千问代码模型全系列,包括6款Qwen2.5-Coder模型,每个规模包含Base和Instruct两个版本。其中32B尺寸的旗舰代码模型在多项基准评测中取得开源最佳成绩,成为全球最强开源代码模型,多项关键能力超越GPT-4o。Qwen2.5-Coder具备强大、多样和实用等优点,通过持续训练,结合源代码、文本代码混合数据及合成数据,显著提升了代码生成、推理和修复等核心任务的性能。此外,该模型还支持多种编程语言,并在人类偏好对齐方面表现出色。本文为周周的奇妙编程原创,阿里云社区首发,未经同意不得转载。
11739 13
|
12天前
|
人工智能 自然语言处理 前端开发
100个降噪蓝牙耳机免费领,用通义灵码从 0 开始打造一个完整APP
打开手机,录制下你完成的代码效果,发布到你的社交媒体,前 100 个@玺哥超Carry、@通义灵码的粉丝,可以免费获得一个降噪蓝牙耳机。
5424 14
|
19天前
|
人工智能 自然语言处理 前端开发
用通义灵码,从 0 开始打造一个完整APP,无需编程经验就可以完成
通义灵码携手科技博主@玺哥超carry 打造全网第一个完整的、面向普通人的自然语言编程教程。完全使用 AI,再配合简单易懂的方法,只要你会打字,就能真正做出一个完整的应用。本教程完全免费,而且为大家准备了 100 个降噪蓝牙耳机,送给前 100 个完成的粉丝。获奖的方式非常简单,只要你跟着教程完成第一课的内容就能获得。
9651 15
|
1月前
|
缓存 监控 Linux
Python 实时获取Linux服务器信息
Python 实时获取Linux服务器信息
|
17天前
|
人工智能 自然语言处理 前端开发
什么?!通义千问也可以在线开发应用了?!
阿里巴巴推出的通义千问,是一个超大规模语言模型,旨在高效处理信息和生成创意内容。它不仅能在创意文案、办公助理、学习助手等领域提供丰富交互体验,还支持定制化解决方案。近日,通义千问推出代码模式,基于Qwen2.5-Coder模型,用户即使不懂编程也能用自然语言生成应用,如个人简历、2048小游戏等。该模式通过预置模板和灵活的自定义选项,极大简化了应用开发过程,助力用户快速实现创意。