SQLite 架构介绍与源码解析
SQLite 是一款广泛使用的嵌入式关系型数据库管理系统,以其轻量级、易用和高效著称。它被广泛应用于移动设备、浏览器、嵌入式系统等场景。本文将详细介绍 SQLite 的架构,并结合其源码解析,帮助您深入理解其内部工作原理。
目录
SQLite 总体架构
SQLite 的架构设计可分为以下几个层次:
- 编译器(Compiler):解析和分析 SQL 语句,生成中间代码。
- 虚拟数据库引擎(Virtual Database Engine, VDBE):执行编译器生成的中间代码。
- 后端存储引擎:包括 B-Tree 模块、Pager 模块和 OS 接口层,负责数据的存储和检索。

核心组件详解
编译器
功能:
- 解析 SQL 语句,将其转换为内部表示(抽象语法树,AST)。
- 进行语法和语义检查。
- 生成 VDBE 可执行的字节码指令。
流程:
- 词法分析(Lexing):将输入的 SQL 文本分解为标记(tokens)。
- 语法分析(Parsing):根据 SQLite 的语法规则,生成抽象语法树。
- 语义分析(Analyzing):检查语义错误,如表不存在、字段类型不匹配等。
- 代码生成(Code Generation):将语法树转换为 VDBE 字节码指令序列。
虚拟机(VDBE)
功能:
- SQLite 的核心执行引擎,负责执行编译器生成的字节码。
- 类似于解释器,逐条执行指令,完成数据库操作。
特点:
- 指令集针对数据库操作进行了优化,如
OpenRead
、Column
、SetNumColumns
等。 - 使用栈式计算模型,操作数通常保存在栈中。
B-Tree 模块
功能:
- 管理数据库文件的逻辑组织,以 B-Tree 结构存储表和索引。
- 提供高效的数据插入、删除、查找和遍历操作。
特点:
- 每个表和索引都对应一个 B-Tree。
- 支持事务和并发控制。
Pager 模块
功能:
- 管理数据库文件的读写,提供页级别的缓存机制。
- 实现事务的原子性、一致性、隔离性和持久性(ACID)。
特点:
- 使用缓存页(Cache Page)来减少磁盘 I/O。
- 实现了日志(Write-Ahead Logging, WAL)和回滚机制。
OS 接口层
功能:
- 抽象底层操作系统的文件和锁机制,提供统一的接口。
- 使 SQLite 能够在不同操作系统上运行。
特点:
- 包含文件读写、文件控制、内存分配、时间获取等接口。
SQLite 工作流程
- 输入 SQL 语句:用户输入一条 SQL 语句。
- 编译器处理:编译器解析 SQL,生成 VDBE 字节码。
- 执行字节码:VDBE 虚拟机执行字节码指令。
- 调用 B-Tree 和 Pager:根据指令,调用 B-Tree 和 Pager 模块进行数据操作。
- 数据存取:通过 OS 接口层,进行磁盘文件的读写操作。
- 返回结果:将查询结果返回给用户。
源码解析
源代码结构
SQLite 的源代码主要由以下几个部分组成:
src/
:核心源码目录。vdbe.c
:虚拟机实现。parse.y
:SQL 语法解析器的 yacc 源文件。btree.c
:B-Tree 模块实现。pager.c
:Pager 模块实现。os_unix.c
、os_win.c
:OS 接口层的不同平台实现。
关键数据结构
Parse
用于存储解析过程中的上下文信息。
1 |
|
Vdbe
表示虚拟机实例。
1 |
|
Btree
表示一个 B-Tree 对象。
1 |
|
Pager
用于管理页面缓存和磁盘 I/O。
1 |
|
执行 SQL 语句的过程
解析阶段(Parser)
- 文件:
parse.y
- 作用:使用 LALR(1) 文法规则解析 SQL 语句,构建抽象语法树(AST)。
- 文件:
语义分析和代码生成
- 文件:
build.c
、expr.c
、select.c
- 作用:对 AST 进行语义检查,并生成对应的 VDBE 字节码。
- 文件:
字节码执行(VDBE)
- 文件:
vdbe.c
- 作用:逐条执行字节码指令,完成数据库操作。
示例:
- 指令
OpenRead
:打开一个 B-Tree 以供读取。 - 指令
Column
:从结果集中取出一列数据。 - 指令
ResultRow
:将结果返回给客户端。
- 文件:
存储引擎操作
B-Tree 模块
- 文件:
btree.c
- 作用:执行对 B-Tree 的增删改查操作。
- 文件:
Pager 模块
- 文件:
pager.c
- 作用:管理页面缓存、事务和日志。
- 文件:
文件 I/O 操作
- 文件:
os_unix.c
、os_win.c
- 作用:封装底层文件系统的操作,实现跨平台兼容。
- 文件:
示例:执行简单的 SELECT 语句
假设执行以下 SQL 语句:
1 |
|
1. 解析和代码生成
解析器将 SQL 文本转换为语法树。
代码生成器根据语法树生成字节码,例如:
1
2
3
4
5
6
7
8
9
100: OpenRead 0, rootPageOfUsersTable
1: Rewind 0
2: Column 0, "age"
3: GreaterThan 30
4: IfNot Jump to 7
5: Column 0, "name"
6: ResultRow
7: Next 0, Jump to 2
8: Close 0
9: Halt
2. 字节码执行
OpenRead
:打开users
表对应的 B-Tree。Rewind
:将游标指向第一条记录。- 循环执行:
Column
:获取当前记录的age
字段。GreaterThan
:判断是否大于 30。IfNot
:如果不满足条件,跳转到Next
。Column
:获取name
字段。ResultRow
:输出结果行。Next
:移动到下一条记录,循环执行。
3. 数据存取
- B-Tree 模块根据游标位置,读取对应的页面。
- Pager 模块从缓存或磁盘中读取页面数据。
- OS 接口层执行实际的文件 I/O 操作。
总结
SQLite 的架构设计精巧,将数据库操作分解为多个层次,每一层次都有明确的职责。通过编译器、虚拟机和存储引擎的协作,实现了对 SQL 语句的高效执行。理解 SQLite 的内部工作原理,有助于我们更好地使用和优化 SQLite 数据库。
关键点:
- 模块化设计:各模块职责清晰,方便维护和扩展。
- 虚拟机执行字节码:提高了执行效率,便于移植。
- 高效的存储引擎:通过 B-Tree 和 Pager 模块,实现了高性能的数据存取。
参考资料:
- SQLite 官方文档:https://www.sqlite.org
- SQLite 源代码:https://www.sqlite.org/download.html
- SQlite源码分析https://huili.github.io/vdbeInt&vdbemem887/whatIsVdbe.html
https://withesse.co/post/sqlite-architecture-explanation-and-code-analysis/