您的位置:首页 > 数据库

derby数据库源码分析(一)--页面分析

2017-08-29 20:50 239 查看
一直以来都对数据库充满了好奇,想知道数据库底层的运作模式,为什么它可以做到高效存储,为什么可以做到ACID,锁机制如何实现。。。等等一系列的问题。

后来找到了Apache的顶级开源项目Derby数据库,该数据库可以支持目前主流的关系型数据库功能,并且代码量不大(20几M)。通过对数据库源代码的研究能够了解更多数据库底层的秘密。

首先先以Derby数据库的底层页面的格式说起。这个页面指的是存储数据库记录的一般页面。Derby数据库的页面默认大小为4096字节。

Format id(2)
页面头部(60)
数据库记录
Slot
校验和(8)
上述表格括号里面的数字表示其占页面的大小,单位是字节。

上述表格中的第一个部分是format id,在derby数据库中对每一个需要存储到磁盘的类分配了一个format id。比如页面对应的类为StoredPage,如果将StoredPage对应的对象写入磁盘时,首先需要将该类对应的format id写入磁盘。这样,当从磁盘读取数据时,可以通过format id找到对应的类,进而在内存中还原该对象。StorePage的format id是117。

每一个页面都有一个页面头部(header),页面头部大小固定,占60个字节。里面包括的内容有:

名字
长度(单位byte)
类型
描述
溢出标志
1
Boolean
表示该页面是否允许溢出
页面状态
1
Byte
 
页面版本
8
Long
页面每修改一次,该字段加一
Slot个数
2
Short
表示该页面中slot的个数
下一个记录id
4
Int
本页面中下一个可以使用的记录id,页面中记录id是唯一的,从6开始。
页面的generation number
4
Int
保留字段,默认值为0
页面前previous generation
4
Int
保留字段,默认值为0
Beforeimage页面的位置
8
 
保留字段,默认值为0
删除的记录数
2
Short
 
空闲百分比
2
Short
为页面更新预留的空间,目前有两个默认值0和20。用户自己创建表的页面是20。
保留空间
2
Short
 
保留空间
4
Int
 
保留空间
8
Long
 
保留空间
8
Long
 
头部信息长度为58个字节。一个页面共有两个状态:VALID_PAGE,INVALID_PAGE。如果页面空间被收回,那么页面状态为INVALID_PAGE,除此之外,页面状态为VALID_PAGE。页面在初始创建的时候,都是VALID_PAGE。

在页面中还有一部分区域叫做slot区域,slot区域中的每一个entry都对应了页面中的一条记录。如果页面大小为4096字节,那么一个entry占6个字节,如果为8192个字节,那么一个entry占12个字节。entry中包括三部分:对应记录在页面中的偏移位置,对应记录的总长度,为对应记录预留的空间长度。从entry中的内容可以看出,entry可以唯一确定一个记录,entry中三个部分的数据均分entry的空间。其中第三个数据为对应记录预留的空间长度的含义是:如果当前记录溢出,那么数据库会为该记录预留一部分空间;如果当前记录过小,以至于不足12个字节,那么数据库也会为当前记录预留一部分空间,以使该记录占的空间大小达到12个字节。页面中slot的空间是倒着增长的,如下图:



从上图就可以看出,页面中的entry是从大地址往小地址增长,而记录是从小地址往大地址增长。
每一个记录由两部分组成:记录头部,若干个列。其中每一个列又分为两部分:列头部,列值。列值存储的就是数据库数据。也就是说,如果对数据库中某一列赋值为字符串“1”,那么列值这一部分就是“1”。列头部和记录头部存储的是控制信息和状态信息。下面分别来说明。

对于记录头部:

名称
长度(单位字节)
说明
记录状态
1
 
记录id
压缩int,长度可以为1,2,4
从6开始
溢出页号
压缩long,长度可以为2,4,8
可以为空
溢出id
压缩int,长度可以为1,2,4
可以为空
第一列
压缩int,长度可以为1,2,4
用于表示第一列是哪一列,从0开始计数
列个数
压缩int,长度可以为1,2,4
当前行中共有多个域
为了节省空间,记录头部大量使用压缩格式存储。记录状态共有四个:

状态
说明
RECORD_DELETED
表示该记录是否已经被删除
RECORD_OVERFLOW
表示该记录是否溢出,如果溢出,那么列值部分填写的内容就是溢出页和溢出id
RECORD_HAS_FIRST_FIELD
表示该记录中含有第一列
RECORD_VALID_MASK
调试使用
列头部:

名称

长度(单位字节)

说明

状态

1

 

数据长度

压缩int,长度可以为1,2,4

 

其中数据长度描述的是列值的长度,单位为字节。列值部分存储的就是具体列的数据了,这一部分针对不同的存储内容,格式也不相同。列状态比较多:

状态

说明

FIELD_INITIAL

 列被初始化后的状态

FIELD_NULL

表示当前列值为null,而且列长度字段也不存储

FIELD_OVERFLOW

表示当前列已经溢出到其他页面中了

FIELD_NOT_NULLABLE

表示当前列已经不存在,例如alter语句将列drop

FIELD_EXTENSIBLE

该列是用户定义的数据类型

FIELD_TAGGED    

当且仅当状态FIELD_EXTENSIBLE的情况下,列状态才可以被设置为FIELD_TAGGED    

FIELD_FIXED

内部状态

上述这些列状态可以组合使用,也就是一个列可以同时处于上表中的多个状态。

未完待续。。。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息