page是数据库在disk层面的最小存储单元。记录被组织在page中,数据库对磁盘的读取,也是以page为单位。因此,研究page的结构是研究数据库实现的基础。我们可以看一下derbydb的page结构。
Derby的page由StoredPage封装。该类维护了page的字节数组(rawDataIn/rawDataOut),并提供了基于DataInput/DataOutput的接口用于访问磁盘。
page结构:
+-----------+-------------+----------+-------------------+----------+
| format id | page header | records | slot offset table | checksum |
+-----------+-------------+----------+-------------------+----------+
简单地讲,一个page被划分为多个slot,每个slot存储一个record。我们可以把page当作储物柜,一个储物柜被划分为大小不一的格子,每一个格子就是一个record空间。slot offset table保存了records的索引。
-- format id
format id是一个4字节的数组,存储了这个page的format id。
-- page header
page header的固定长度是56字节。下面是每一个字节的含义:
1 byte boolean 标识该page是否是一个溢出的page
2 byte byte page的状态
8 bytes long page的版本号
2 bytes unsigned short slog offset table中的slot数目
4 bytes integer 下一个记录的标识符
4 bytes integer 该page的代号(未来使用)
4 bytes integer 该page的上一代号(未来使用)
4 bytes integer
2 bytes unsigned short 该page中被删除的行数
2 bytes unsigned short 为修改用的空闲空间百分比
2 bytes short 空闲区域,未来使用
4 bytes long 空闲区域,未来使用(加密算法会写一个随机数到该字段)
8 bytes long 空闲区域,未来使用
8 bytes long 空闲区域,未来使用
这里需要指出的是,空闲区域被写入的是0。
-- records
records区域用于保存record数据,record记录可以是零个或多个。
在描述records区域之前,我们需要关注一个变量:minimumRecordSize。该属性定义了最小的用户记录长度,这个长度不包括数据库系统添加的record头和字段头。我们可以认为,当一个record被插入时,record总共所需的最少字节数是minimumRecordSize与数据库添加的头长度之和。
举个例子:
假设minimumRecordSize为10。
如果用户的记录长度为7字节,我们使用5字节保存record头和字段头信息,那么被写到磁盘的record实际上占用15字节(10 + 5)。其中,3个字节是空的。
如果用户的记录长度为17字节,我们使用5字节保存record头和字段头信息,那么被写到磁盘的record实际上占用22字节(17 + 5)。
+-------------------------+
| record1 | record2 | ... |
+-------------------------+
-- slot offset table
正如该区域的名字所指出的那样,该区域保存了每一个record在page的偏移量信息。该表的每一个元素对应每一个record。每一个元素的长度是6或12字节,这个长度取决于page是否小于64K。
每一个元素包括下面几部分:
* 2字节(unsigned short)或4字节(int)的页偏移量。
* 2字节(unsigned short)或4字节(int)的record长度。
* 2字节(unsigned short)或4字节(int)的多余空间。
StoredPage的变量slotTableOffsetToFirstEntry定义了第一个slot元素在page的起始位置,可以认为是整个slot offset table的偏移量。这里有一个很有意思的事情是,slot offset table的元素是从后往前写的。所以,一个slot offset table的结构大概是:
+-------------------------------------+----------+
| ... | slot3 | slot2 | slot1 | slot0 | checksum |
+-------------------------------------+----------+
| <------ slot offset table ----->|
-- checksum
每个page的最后8字节是校验和。这个校验和是利用java.util.zip.CRC32对整个page计算得到的。
StoredPage
前面说到StoredPage封装了一个page的信息,并且提供了众多和外界交互的接口。我们首先考察StoredPage封装的重要数据。
slotsInUse:
是一个整型变量,标识这个page拥有的record数量。这个变量被存储在page的头部,当page从文件读出时,这个变量会从page头读出。
headers:
headers是一个元素为StoredRecordHeader的数组。当page从文件读出时,headers会根据slotsInUse初始化。所以,可以认为,在任意时刻,headers的长度和slotsInUse相同。
pageData:
是一个字节数组,保存了该page的所有原始数据。当一个page从磁盘加载进内存时,这个数组会被初始化。
setIdentity(Object key):
setIdentity方法根据一个PageKey,从FileContainer读取该page的所有数据,并初始化一些实例变量。实际上StoredPage继承了CachedPage,setIdentity方法定义在CachedPage,setIdentity会调用定义在StoredPage的initFromData做真正初始化的动作。
相关推荐
Derby的系统表结构,列出Derby的系统表及表结构
java derby数据库,包含jar文件和官方教程
db-derby-10.11.1.1-bin.zip,apache derby 相当于java db(derby)的完整版
Derby Developer's Guide. Purpose of this guide This guide explains how to use the core Derby technology and is for developers building Derby applications. It describes basic Derby concepts, such as ...
db-derby-10.11.1.1-src.zip,derby数据库源码
derby个人小型数据库,嵌入式以及服务器模式两种启动模式
db-derby-10.13.1.1-bin.tar.gz
试过了,可以用的。这次没有出现 数据库连接错误的问题
birt-example-db-ds OSGi 项目设置为使用随 BIRT 报告提供的示例 DerbyDB。 用于此的 P2 存储库是:
db-derby-10.6.2.1-bin.tar.gz
讲述derby使用问题
收集的学习资料,包括:Derby数据库(V10.9)用户手册(PDF版),用 Apache Derby 进行 Java 数据库开发,用 Apache Derby 进行数据库开发,03开源项目(三)嵌入式数据库Apache Derby(1)(开发指南).pdf ,Apache Derby ...
derby配置
jdk内置数据库,有兴趣的可以玩一玩。文件分别为:db-derby-10.10.1.1-bin.zip、derby_core_plugin_10.2.2.485682.zip、derby_ui_plugin_1.1.0.zip。
Derby数据库完整压缩包,解压缩即可使用,bat文件在bin文件目录下,驱动程序在lib目录下。 Apache Derby非常小巧,核心部分derby.jar只有2M,所以既可以做为单独的数据库服务器使用,也可以内嵌在应用程序中使用。...
Derby用户手册 最好的了解derby的资源
朋友手工制作,derby数据库和其他数据库的转换工具,简易实用。高手可直接用命令提示符便可使用该工具
derby.jar activation.jar jspsmartupload.jar及各种包
myeclipse本地方式连接Derby
Eclipse插件Derby安装 Derby插件开发