您好,欢迎访问三七文档
当前位置:首页 > 办公文档 > 招标投标 > SQLite文件格式分析_v102
SQLite数据库文件格式全面分析作者:空转0前言性急的兄弟可以跳过前言直接看第1章,特别性急的兄弟可以跳过前面各章,直接看鸣谢。SQLite数据库包括多方面的知识,比如VDBE什么的。据说那些东西会经常变。确实,我用的是3.6.18版,我看跟其它文档中描述的3.3.6的VDBE已经很不一样了。所以决定先写文件格式,只要是3.?.?的版本,文件格式应该不会有太大变化吧。网上介绍SQLite文件格式的文章并不少,但一般都是针对小文件:一个表,几条记录,两个页。本文准备一直分析到比较大的文件,至少B-tree和B+tree中得有内结点(就是说不能只有一个既是根又是叶的结点,就是说表中得多点记录,得建索引),还要争取对SQLite的各类页都做出分析。在分析的过程中,争取把SQLite数据库关于文件格式的基本规定也都介绍一下。这样,本文既是一个综合性的技术文档,又带有实例说明,兄弟们参考时岂不是就很方便了吗?既然是技术文档,要想读懂总得先掌握点SQLite数据库的基本知识吧。所以,先介绍参考文献。0.1参考文献1-TheDefinitiveGuidetoSQLite.MichaelOwens:比较经典的SQLite著作。我边看边翻译了其中的部分内容,但翻得不好,大家还是看原文吧。2-SQLite源代码:有关SQLite的最原始说明都在源代码中了。先浏览一下代码还是很有收获的,特别是几个主要的.h文件。有关文件格式的说明主要在btreeInt.h中。3-SQLite入门与分析:网上Arrowcat的系列文章。Arrowcat应该是一个很博学的人,看他的文章收获很大,在此也算是鸣谢吧。4-SQLite.ChrisNewman:我没看,因为也是网上能够下载到的重要资源,所以列出。看目录内容应该比参考文献1简单一些,但出版日期也更早了一些。5-NULL:在网上搜了半天,国内为什么就没有关于SQLite的好书呢?6-:如果这篇文章看懂了,其实我这篇东西根本就不用再看了。这是介绍SQLite文件格式的权威文档,列在最后,是因为我也是写完这篇东西后才看到的。该文档由SQLite官方网站提供,当初没看,一是因为上网少,还没仔细浏览人家的网站就开始干了(太激动),其实归根结蒂还是因为英语不好。看到此文档这后还敢把我的东西发出来,有两个原因:一、为其他英语比我强不了多少的兄弟提供一点方便,二、我这里有例子,看起来更形象一些吧。0.2术语本文涉及的绝大多数术语都是在出现时再进行简单解释,但还是有个别概念需要先说明清楚,比如:(1)Btree、B-tree和B+tree:Btree是为磁盘存储而优化了的一种树结构,其一般性说明可参考各类《数据结构》教材。根据实现方法的不同,Btree又分为很多类型。在SQLite中,存储表数据用的是B+tree,存储表索引用的是B-tree。由于历史原因,SQLite在3.0版以前只使用B-tree,从3.0版开始,才对表数据使用了B+tree。因此,在SQLite的官方文档中,有时B-tree表示存储表索引的B-tree,有时又是两种Btree的统称。本文中将两种Btree的概念加以了区分,而将Btree作为两种树的统称,这是与SQLite官方文档及当前大多数SQLite介绍性文档相区别的地方。(2)auto-vacuum数据库:一般情况下,当一个事务从数据库中删除了数据并提交后,数据库文件的大小保持不变。即使整页的数据都被删除,该页也会变成“空闲页”等待再次被使用,而不会实际地被从数据库文件中删除。执行vacuum操作,可以通过重建数据库文件来清除数据库内所有的未用空间,使数据库文件变小。但是,如果一个数据库在创建时被指定为auto_vacuum数据库,当删除事务提交时,数据库文件会自动缩小。使用auto_vacuum数据库可以节省空间,但却会增加数据库操作的时间,有利有弊。Auto_vacuum数据库需要使用附加的格式,如指针图页(本文第6章有介绍),本文重点讨论非auto_vacuum数据库。(3)数据库映像、数据库文件和日志文件:“数据库映像”是SQLite数据库的磁盘映像。SQLite数据库存储在单一的“数据库文件”中。一般情况下,数据库映像和数据库文件是一致的,可以理解为数据库映像就是数据库文件的内容,但有例外。如果事务对数据库进行了修改,这些修改会暂存在“日志文件”中,此时可以认为数据库映像分布在数据库文件和日志文件两个文件中。日志文件有自己的格式,本文第7章专门介绍。(4)SQLite的当前版本:我开始写这篇东西时,SQLite的当前版本为3.6.18。现在已经变成3.6.20了,文件格式没变。1小文件的分析1.1准备数据库执行SQLite的命令行工具,创建一个新的数据库food_test.db。D:\SQLite\CLPsqlite3foods_test.db创建一个新表。CREATETABLEfoods(idintegerprimarykey,type_idinteger,nametext);插入2条记录。INSERTINTOfoodsVALUES(1,1,'Bagels');INSERTINTOfoodsVALUES(2,1,'Bagels,raisin');退出命令行工具。当前目录下多了一个文件foods_test.db,大小为2K。现在,就可以用UltraEdit或WinHex之类的软件对其进行分析了。1.2SQLite文件格式SQLite有3类数据库。除内存数据库外,SQLite把每个数据库(main或temp)都存储到一个单独的文件中。SQLite数据库文件由固定大小的“页(page)”组成。页的大小可以在512~32768之间(包含这两个值,必须是2的指数),默认大小为1024个字节(1KB)。页大小可以在数据库刚刚创建时设置,一旦创建了数据库对象之后,这个值就不能再改变了。数据库中所有的页从1开始顺序编号。在具体的实现中,页号用4字节来表示,并限制最大页号不得超过2^31(参pager.c)。文件的第1个页被称为page1,第2个页被称为page2,依此类推。编号为0的页表示“无此页”。注:关于一个数据库文件中可以有多少个页,SQLite是这样实现的:为了限制数据库文件的大小(不要太大),SQLite在程序中对文件页数进行了限制,文件页数的最大值默认为1073741823,在sqliteLimit.h中定义,可以在运行时改变。页的类型可以是:Btree页、空闲(free)页或溢出(overflow)页。Btree又可以是B-tree或B+tree,每一种树的结点又区分为内部页和叶子页。一个数据库文件中可能没有空闲页或溢出页,但必然有Btree页。关于Btree页的格式规定是SQLite数据库的核心内容,本文的前半部分都是在介绍Btree页。注:其实SQLite还有两种页。一种称为“锁页(lockingpage)”。只有1页,位于数据库文件偏移为1G开始的地方,如果文件不足1G,就没有此页。该页是用于文件加锁的区域,不能存储数据(参源代码io.h)。好在,如果只是读数据,即使文件大于1G,也不会有指针指向此页,因此下面我们就不再提它了。另一种称为“指针位图页(pointer-mappage)”,这类页用于在auto-vacuum的数据库中存储元数据。本文不涉及auto-vacuum数据库,也就不讨论这种页了。从逻辑上来说,一个SQLite数据库文件由多个多重Btree构成。每个Btree存储一个表的数据或一个表的索引,索引采用B-tree,而表数据采用B+tree,每个Btree占用至少一个完整的页,每个页是Btree的一个结点。每个表或索引的第1个页称为根页,所有表或索引的根页编号都存储在系统表sqlite_master中,表sqlite_master的根页为page1。注:sqlite_master是一个系统表,保存了数据库的schema信息,详参“关于sqlite_master表”一节。数据库中第一个页(page1)永远是Btree页。Page1的前100个字节是一个对数据库文件进行描述的“文件头”。它包括数据库的版本、格式的版本、页大小、编码等所有创建数据库时设置的永久性参数。关于这个特殊文件头的文档在btreeInt.h中,具体格式如下:偏移量大小说明016头字符串,如果不改源程序,此字符串永远是SQLiteformat3。162页大小(以字节为单位)。181文件格式版本(写)。对于SQLite的当前版本,此值为1。如果该值大于1,表示文件为只读。SQLite将来版本对此域的规定可能改变。191文件格式版本(读)。对于SQLite的当前版本,此值为1。如果该值大于1,SQLite认为文件格式错,拒绝打开此文件。SQLite将来版本对此域的规定可能改变。201每页尾部保留空间的大小。(留作它用,默认为0。)211Btree内部页中一个单元最多能够使用的空间。255意味着100%,默认值为0x40,即64(25%),这保证了一个结点(页)至少有4个单元。221Btree内部页中一个单元使用空间的最小值。默认值为0x20,即32(12.5%)。231Btree叶子页中一个单元使用空间的最小值。默认值为0x20,即32(12.5%)。注:SQLite的当前版本规定21~23的3个字节值只能是0X402020。原来这3个字节值是可变的,从3.6.0版开始被固定下来了。244文件修改计数,通常被事务使用,由事务增加其值。SQLite用此域的值验证内存缓冲区中数据的有效性。284未使用。324空闲页链表首指针。参“空闲页”一节。364文件内空闲页的数量。406015个4字节的元数据变量。从偏移40开始的15个4字节元数据变量在btreeInt.h中的定义如下:404Schema版本:每次schema改变(创建或删除表、索引、视图或触发器等对象,造成sqlite_master表被修改)时,此值+1。444Fileformatofschemalayer:当前允许值为1~4,超过此范围,将被认为是文件格式错。484Sizeofpagecache。524Largestroot-page(auto/incr_vacuum):对于auto-vacuum数据库,此域为数据库中根页编号的最大值,非0。对于非auto-vacuum数据库,此域值为0。5641=UTF-8、2=UTF16le、3=UTF16be。604Userversion。此域值供用户应用程序自由存取,其含义也由用户定义。644Incrementalvacuummode:对于auto-vacuum数据库,如果是Incrementalvacuum模式,此域值为1。否则,此域值为0。684未使用。724未使用。用UltraEdit打开文件foods_test.db,page1在0X0000~0X03FF。其中文件头内容如下(深蓝色部分):前16个字节为头字符串,程序中固定设为SQLiteformat3。0X0400:页大小,0X0400=1024字节。0X01:文件格式版本(写),值为1。0X01:文件格式版本(读),值为1。0X40:Btree内部页中一个单元最多能够使用的空间。0X40=64,即25%。0X20:Btree内部页中一个单元使用空间的最小值。0X20=32,即12.5%。0X20:Btree叶子页中一个单元使用空间的最小值。0X20=32,即12.5%。0X00000003:文件修改计数,现在已经修改了3次,分别是1次创建和两次插入。从0X20开始的4个字节:空闲页链表首指针。当前值为0,表示该链表为空。从0X24开始的4个字节:文件内空闲页的数量。当前值为0。从0X28开始的4个字节:Schemaversion。当前值为0X00000001。以后,每次sqlite_master表被修改时,此值+1。从0X38开始的4个字节:采用的字符编码
本文标题:SQLite文件格式分析_v102
链接地址:https://www.777doc.com/doc-4405799 .html