SQLite架构

本文译自《Architecture of SQLite》

介绍

这篇文档描述了SQLite库的架构。如果想理解SQLite内部原理,或者对它进行修改,这篇文档提供了有帮助的信息。

下图展示了SQLite的主要组件和它们的协作方式。后文解释了这些组件的具体职责。

SQLite模块

本文中各组件的原文译文对照:

原文 译文
Interface 接口
SQL Command Processor SQL命令处理器
Virtual Machine 虚拟机
Tokenizer 词法分析器
Parser 语法分析器
B-Tree B树
Pager 页缓存
OS Interface OS接口
Utilities 通用库
Test Code 测试代码

概览

SQLite的工作流程是将SQL文本编译成字节码,然后在虚拟机上运行这些字节码。

sqlite3_prepare_v2()和相关的接口起到编译器的作用,将SQL文本转化为字节码。sqlite3_stmt对象是一个字节码容器,存储了单条SQL语句所编译出的字节码。sqlite3_step()接口将字节码程序传给虚拟机,执行字节码程序直到它完成、返回结果集、遇到严重错误或被中断(interrupted)。

接口

C语言接口主要在main.clegacy.cvdbeapi.c中,也有一些接口分散在其他文件中,这是为了使它们能使用一些文件私有的数据结构。sqlite3_get_table()例程在table.c中,sqlite3_mprintf()printf.c中,sqlite3_complete()tokenize.c中,TCL Interfacetclsqlite.c中。

为避免名称冲突,SQLite库中的所有外部符号都以前缀sqlite3开头。那些用于外部使用的符号,也就是出现在SQLite API中的符号,会添加一个下划线,从而以sqlite3_开头。扩展API有时会在下划线之前添加扩展名,例如:sqlite3rbu_或sqlite3session_。

词法分析器

当一条SQL语句要被编译时,它首先被发送给词法分析器。

词法分析器将SQL文本分解成词,然后将它一个个交给语法分析器。词法分析器的文件是tokenize.c,其中的代码是手工写的。

注意此处的设计,是词法分析器调用语法分析器。熟悉YACC或者BISON的人可能习惯于反过来——让语法分析器调用词法分析器。前者更好,因为它可以做到线程安全,并且运行地更快。

语法分析器

语法分析器根据词的上下文赋予它语义。

SQLite的语法分析器通过Lemon LALR(1)生成。Lemon的功能和YACC、BISON类似,但是它所使用的输入语法更不容易出错。同时Lemon生成的语法分析器是可重入和线程安全的。Lemon定义了“非终结符析构器(non-terminal destructor)”的概念,因此它在遇到语法错误时不会泄露内存。Lemon所需的语法文件是parse.y,其中定义了SQLite使用的SQL语法。

因为Lemon很可能不在开发机器上,它完整的源代码在SQLite的tool文件夹中,仅有一个C文件。

代码生成器

语法分析器将词转化为语法树,代码生成器分析语法树,并且生成符合SQL功能的字节码。

prepared statement对象是这段字节码的容器。代码生成器包含很多文件:attach.c,** auth.cbuild.cdelete.cexpr.cinsert.cpragma.cselect.ctrigger.cupdate.cvacuum.cwhere.cwherecode.c以及whereexpr.c**。SQLite的魔法大多发生在这些文件中。

expr.c处理表达式的代码生成,where.c处理SELECT,UPDATE,DELETE语句的WHERE子句的代码生成。attach.cdelete.cinsert.cselect.ctrigger.cupdate.c,和vacuum.c处理和文件名对应的SQL语句的代码生成,其中每个文件都需要调用expr.cwhere.c中的例程。其他所有的SQL语句都由build.c处理。auth.c*实现了sqlite3_set_authorizer()的功能。

代码生成器,特别是where.cselect.c中的逻辑部分,有时被称作查询计划器query planner。对于任何一条SQL语句,可能有成百上千种不同的算法能得出结果。查询计划器是一个AI,尽力从其中选出最好的算法。

字节码引擎

生成器输出的代码最终由虚拟机来执行。

虚拟机本身完全包含在单个文件中,即vdbe.c文件。vdbe.h头文件定义了其他SQLite库与虚拟机之间的接口,而vdbeInt.h定义了虚拟机私有的数据结构和接口。

剩下的多个vdbe.c文件是虚拟机的辅助代码。vdbeaux.c文件包含了虚拟机使用的通用库,以及其他库用来构造VM程序的接口模块。vdbeapi.c文件包含了虚拟机的外部接口,比如sqlite3_bind_int()sqlite3_step()。单个值(字符串,整数,浮点数,二进制数据)存储在一个内部对象“Mem”中,该对象在vdbemem.c*实现。

SQLite通过回调C语言来实现SQL的函数。甚至内置的SQL函数也通过这种方式实现。大部分内置SQL函数,例如abs()count()substr()等,都写在func.c文件中。日期时间转换函数写在date.c中。一些函数,例如coalesce()typeof()直接被代码生成器实现为字节码。

B树

SQLite使用B树结构来维护磁盘上的数据,B树的实现在btree.c文件中。

数据库中每个表和索引都使用单独的B树。全部的B树都存储在同一个磁盘文件中。文件格式的规格是明确且稳定的,并且保证向前兼容。

B树子系统对其他SQLite库的接口定义在头文件btree.h中。

页缓存

B树模块要求磁盘上的信息具有固定的页面大小。默认的页面大小(page_size)是4096字节,但是也可以设置为512到65536之间的2的整数幂。页缓存负责页面的读写和缓存。页缓存也提供回滚和原子性提交的抽象,并且负责对数据库文件加锁。

B树模块向页缓存请求页面,并且在修改页面,提交或回滚时通知页缓存。页缓存会处理大量的细节,以确保请求被快速,安全,高效地处理。

主要的页缓存实现是在pager.c文件中,WAL模式的逻辑在单独的wal.c中,内存型缓存实现在pcache.cpcache1.c文件中。页缓存子系统对其他SQLite库的接口定义在pager.h中。

OS接口

为了提供跨操作系统移植性,SQLite使用名为VFS的抽象对象。每个VFS提供对磁盘文件的打开、关闭以及读写方法,以及其他特定于操作系统的功能,如获得当前时间,为伪随机数生成器设置随机种子等。

SQLite目前对unix和Windows提供VFS,分别在os_unix.cos_win.c文件中。

通用类

内存分配,大小写不敏感的字符串比较例程,可移植的字符串到数字转换例程,以及其他通用库位于util.c中。

hash.c实现了哈希表结构,在语法解析器中被用作符号表。utf.c源文件包含Unicode转换的相关例程。在printf.c中,SQLite实现了自己私有的printf(),包含了一些拓展。在random.c中,SQLite也实现了自己的伪随机数生成器。

测试代码

在src文件夹中,以test开头的文件为测试代码,不被包含在标准库版本中。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容