derby数据库源码分析(一)--页面分析
2017-08-29 20:50
239 查看
一直以来都对数据库充满了好奇,想知道数据库底层的运作模式,为什么它可以做到高效存储,为什么可以做到ACID,锁机制如何实现。。。等等一系列的问题。
后来找到了Apache的顶级开源项目Derby数据库,该数据库可以支持目前主流的关系型数据库功能,并且代码量不大(20几M)。通过对数据库源代码的研究能够了解更多数据库底层的秘密。
首先先以Derby数据库的底层页面的格式说起。这个页面指的是存储数据库记录的一般页面。Derby数据库的页面默认大小为4096字节。
上述表格括号里面的数字表示其占页面的大小,单位是字节。
上述表格中的第一个部分是format id,在derby数据库中对每一个需要存储到磁盘的类分配了一个format id。比如页面对应的类为StoredPage,如果将StoredPage对应的对象写入磁盘时,首先需要将该类对应的format id写入磁盘。这样,当从磁盘读取数据时,可以通过format id找到对应的类,进而在内存中还原该对象。StorePage的format id是117。
每一个页面都有一个页面头部(header),页面头部大小固定,占60个字节。里面包括的内容有:
头部信息长度为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”。列头部和记录头部存储的是控制信息和状态信息。下面分别来说明。
对于记录头部:
为了节省空间,记录头部大量使用压缩格式存储。记录状态共有四个:
列头部:
其中数据长度描述的是列值的长度,单位为字节。列值部分存储的就是具体列的数据了,这一部分针对不同的存储内容,格式也不相同。列状态比较多:
上述这些列状态可以组合使用,也就是一个列可以同时处于上表中的多个状态。
未完待续。。。。。。
后来找到了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 | |
在页面中还有一部分区域叫做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 | 内部状态 |
未完待续。。。。。。
相关文章推荐
- derby数据库源码分析(三)–页面分析
- derby数据库源码分析(二)--页面分析
- derby数据库源码分析(二)--页面分析
- 数据库中间件 MyCAT 源码分析 —— 调试环境搭建
- Android数据库ORM框架用法、源码和性能比较分析
- 数据库中间件 MyCAT 源码分析 —— 【单库单表】查询
- 【oschina android源码分析】聊天页面(私信)的设计
- SugarORM 数据库升级流程源码分析
- 数据库中间件 MyCAT 源码分析 —— XA分布式事务
- ArcSDE在没有源码的情况下支持国产数据库的可能性分析
- [置顶] j2ee页面静态化方案encache web cache框架源码分析2
- 数据库中间件 MyCAT 源码分析 —— 调试环境搭建
- 数据库中间件 MyCAT 源码分析 —— 【单库单表】查询
- Android数据库一些源码分析
- Solr1.4.0源码分析(一) 解决DataImportHandler从数据库导入大量数据而内存溢出的问题
- j2ee页面静态化方案encache web cache框架源码分析2
- Laravel 5 配置数据库主从读写分离和源码分析
- 数据库中间件 Sharding-JDBC 源码分析 —— SQL 解析(三)之查询SQL解析
- 【WPF学习笔记】之如何把数据库里的值读取出来然后显示在页面上:动画系列之(六)(评论处有学习资料及源码)
- redis源码分析(5)-- redis数据库