架構(architecture)
SQLite采用了模塊的設計,它由三個子系統,包括8個獨立的模塊構成。
1.接口(Interface)
接口由SQLite C API組成,也就是說不管是程序、腳本語言還是庫文件,最終都是通過它與SQLite交互的(我們通常用得較多的ODBC/JDBC最后也會轉化為相應C API的調用)。
2.編譯器(Compiler)
在編譯器中,分詞器(Tokenizer)和分析器(Parser)對SQL進行語法檢查,然后把它轉化為底層能更方便處理的分層的數據結構---語法樹,然后把語法樹傳給代碼生成器(code generator)進行處理。而代碼生成器根據它生成一種針對SQLite的匯編代碼,最后由虛擬機(Virtual Machine)執行。
3.虛擬機(Virtual Machine)
架構中最核心的部分是虛擬機,或者叫做虛擬數據庫引擎(Virtual Database Engine,VDBE)。它和Java虛擬機相似,解釋執行字節代碼。VDBE的字節代碼由128個操作碼(opcodes)構成,它們主要集中在數據庫操作。它的每一條指令都用來完成特定的數據庫操作(比如打開一個表的游標)或者為這些操作棧空間的准備(比如壓入參數)。總之,所有的這些指令都是為了滿足SQL命令的要求(關於VM,后面會做詳細介紹)。
4.后端(Back-End)
后端由B-樹(B-tree),頁緩存(page cache,pager)和操作系統接口(即系統調用)構成。B-tree和page cache共同對數據進行管理。B-tree的主要功能就是索引,它維護着各個頁面之間的復雜的關系,便於快速找到所需數據。而pager的主要作用就是通過OS接口在B-tree和Disk之間傳遞頁面。
SQLite的體系結構
下圖是一個體系結構圖,顯示了SQLite的主要組件以及各組件之間是如何相互關聯的。
在內部,SQLite由以下幾個組件組成:內核、SQL編譯器、后端以及附件。SQLite通過利用虛擬機和虛擬數據庫引擎(VDBE),使調試、修改和擴展SQLite的內核變得更加方便。所有SQL語句都被編譯成易讀的、可以在SQLite虛擬機中執行的程序集。SQLite支持大小高達2 TB的數據庫,每個數據庫完全存儲在單個磁盤文件中。這些磁盤文件可以在不同字節順序的計算機之間移動。這些數據以B+樹(B+tree)數據結構的形式存儲在磁盤上。SQLite根據該文件系統獲得其數據庫權限。
1、公共接口(Interface)
SQLite庫的大部分公共接口由main.c, legacy.c和vdbeapi.c源文件中的函數來實現,這些函數依賴於分散在其他文件中的一些程序,因為在這些文件中它們可以訪問有文件作用域的數據結構。sqlite3_get_table()例程在table.c中實現,sqlite3_mprintf()可在printf.c中找到,sqlite3_complete()則位於tokenize.c中。Tcl接口在tclsqlite.c中實現。SQLite的C接口信息可參考http://sqlite.org/capi3ref.html。
為了避免和其他軟件的名字沖突,SQLite庫的所有外部符號都以sqlite3為前綴,這些被用來做外部使用的符號(換句話說,這些符號用來形成SQLite的API)是以sqlite3_開頭來命名的。
2、詞法分析器(Tokenizer)
當執行一個包含SQL語句的字符串時,接口程序要把這個字符串傳遞給tokenizer。Tokenizer的任務是把原有字符串分割成一個個標識符(token),並把這些標識符傳遞給解析器。Tokenizer是用手工編寫的,在C文件tokenize.c中。
在這個設計中需要注意的一點是,tokenizer調用parser。熟悉YACC和BISON的人們也許會習慣於用parser調用tokenizer。SQLite的作者已經嘗試了這兩種方法,並發現用tokenizer調用parser會使程序運行的更好。YACC會使程序更滯后一些。
3、語法分析器(Parser)
語法分析器的工作是在指定的上下文中賦予標識符具體的含義。SQLite的語法分析器使用Lemon LALR(1)分析程序生成器來產生,Lemon做的工作與YACC/BISON相同,但它使用不同的輸入句法,這種句法更不易出錯。Lemon還產生可重入的並且線程安全的語法分析器。Lemon定義了非終結析構器的概念,當遇到語法錯誤時它不會泄露內存。驅動Lemon的源文件可在parse.y中找到。
因為lemon是一個在開發機器上不常見的程序,所以lemon的源代碼(只是一個C文件)被放在SQLite的"tool"子目錄下。 lemon的文檔放在"doc"子目錄下。
4、代碼生成器(Code Generator)
語法分析器在把標識符組裝成完整的SQL語句后,就調用代碼生成器產生虛擬機代碼,以執行SQL語句請求的工作。代碼生成器包含許多文件:attach.c, auth.c, build.c, delete.c, expr.c, insert.c,pragma.c, select.c, trigger.c, update.c, vacuum.c和where.c。這些文件涵蓋了大部分最重要、最有意義的事情。expr.c處理SQL中表達式的代碼生成。where.c處理SELECT、UPDATE和DELETE語句中WHERE子句的代碼生成。文件attach.c, delete.c, insert.c, select.c, trigger.c, update.c和vacuum.c處理同名SQL語句的代碼生成(這些文件在必要時都調用expr.c和where.c中的例程)。所有其他SQL語句的代碼由build.c生成。文件auth.c實現sqlite3_set_authorizer()的功能。
5、虛擬機(Virtual Machine)
代碼生成器生成的代碼由虛擬機來執行。關於虛擬機更詳細的信息可參考http://sqlite.org/opcode.html。總的來說,虛擬機實現一個專為操作數據庫文件而設計的抽象計算引擎。它有一個存儲中間數據的存儲棧,每條指令包含一個操作碼和不超過三個額外的操作數。
虛擬機本身被完整地包含在一個單獨的文件vdbe.c中,它也有自己的頭文件,其中vdbe.h定義虛擬機與SQLite庫其他部分之間的接口,vdbeInt.h定義虛擬機私有的數據結構。文件vdbeaux.c包含被虛擬機使用的一些工具,和被庫的其他部分用來構建VM程序的一些接口模塊。文件vdbeapi.c包含虛擬機的外部接口,例如sqlite3_bind_...族的函數。單獨的值(字符串、整數、浮點數、BLOB對象)被存儲在一個叫Mem的內部對象中,在vdbemem.c中可找到它的實現。
SQLite使用回調風格的C語言程序來實現SQL函數,每個內建的SQL函數都用這種方式來實現。大多數內建的SQL函數(例如coalesce(), count(), substr(), 等等)可在func.c中找到。日期和時間轉換函數可在date.c中找到。
6、B-樹(B-Tree)
一個SQLite數據庫使用B-樹的形式存儲在磁盤上,B-樹的實現位於源文件btree.c中。數據庫中的每個表和索引使用一棵單獨的B-樹,所有的B-樹存放在同一個磁盤文件中。文件格式的細節被記錄在btree.c開頭的備注里。B-樹子系統的接口在頭文件btree.h中定義。
7、頁面高速緩存(Page Cache)
B-樹模塊以固定大小的數據塊形式從磁盤上請求信息,默認的塊大小是1024個字節,但是可以在512和65536個字節之間變化。頁面高速緩存負責讀、寫和緩存這些數據塊。頁面高速緩存還提供回滾和原子提交的抽象,並且管理數據文件的鎖定。B-樹驅動模塊從頁面高速緩存中請求特定的頁,當它想修改頁面、想提交或回滾當前修改時,它也會通知頁面高速緩存。頁面高速緩存處理所有麻煩的細節,以確保請求能夠快速、安全而有效地被處理。
頁面高速緩存的代碼實現被包含在單一的C源文件pager.c中。頁面高速緩存子系統的接口在頭文件pager.h中定義。
8、OS接口
為了在POSIX和Win32操作系統之間提供移植性,SQLite使用一個抽象層來提供操作系統接口。OS抽象層的接口在os.h中定義,每種支持的操作系統有各自的實現:Unix使用os_unix.c,Windows使用os_win.c,等等。每個特定操作系統的實現通常都有自己的頭文件,如os_unix.h, os_win.h等。
9、實用工具(Utilities)
內存分配和字符串比較函數位於util.c中。語法分析器使用的符號表用Hash表來維護,其實現位於hash.c中。源文件utf.c包含Unicode轉換子程序。SQLite有自己的printf()實現(帶一些擴展功能),在printf.c中,還有自己的隨機數生成器,在random.c中。
10、測試代碼(Test Code)
如果你計算回歸測試腳本,超過一半的SQLite代碼將被測試。主要代碼文件中有許多assert()語句。另外,源文件test1.c通過test5.c和md5.c實現只用於測試目的的一些擴展。os_test.c后端接口用來模擬斷電,以驗證頁面高速緩存的崩潰恢復機制。
SQLite Version3.3.6源代碼文件結構
文件名稱 | 大小byte | 備注 | |
API | main.c | 35414 | SQLite Library的大部分接口 |
legacy.c | 3734 | sqlite3_exec的實現 | |
table.c | 5464 | the sqlite3_get_table() and sqlite3_free_table()的實現,它們是sqlite3_exec的包裝 | |
preprare.c | 17983 | 主要實現sqlite3_prepare() | |
分詞器部分(Tokenizer) | tokenize.c | 14495 | 分詞器的實現 |
語法分析器部分(Parser) | parser.c | 116917 | 分析器的實現,由Lemon實現 |
parser.h | 6847 | 分析器內部定義的關鍵字 | |
代碼生成器(Code Generator) | update.c | 23878 | 處理UPDATTE語句 |
delete.c | 21978 | 處理DELETE語句 | |
insert.c | 62026 | 處理INSERT語句 | |
trigger.c | 29065 | 處理TRIGGER語句 | |
attach.c | 15941 | 處理ATTACHT 和DEATTACH語句 | |
select.c | 112084 | 處理SELECT語句 | |
where.c | 75826 | 處理WHERE語句 | |
vacuum.c | 11005 | 處理VACUUM語句 | |
pragma.c | 34289 | 處理PRAGMA命令 | |
expr.c | 73963 | 處理SQL語句中的表達式 | |
auth.c | 7496 | 主要實現sqlite3_set_authorizer() | |
analyze.c | 13149 | 實現ANALYZE命令 | |
alter.c | 18414 | 實現ALTER TABLE功能 | |
build.c | 104052 | 處理以下語法:CREATE TABLE, DROP TABLE, CREATE INDEX,DROP INDEX,creating ID lists,BEGIN TRANSACTION,COMMIT,ROLLBACK | |
func.c | 34335 | 實現SQL語句的函數語句 | |
date.c | 24031 | 與日期和時間轉換有關的函數 | |
虛擬機(Virtual Machine) | vdbeapi.c | 23300 | 虛擬機提供上層模塊調用的API實現部分 |
vdbe.c | 143552 | 虛擬機的主要實現部分 | |
vdbe.h | 5309 | 定義了VDBE的接口,VdbeOp結構體(代表一條指令) | |
vdbeaux.c | 58741 | Vdbe.h的接口的實現 | |
vdbeInt.h | 17595 | Vdbe.c的私有頭文件,定義了VDBE常用的數據結構:Cursor——虛擬機中使用的游標, Mem——vdbe在內部把所有的SQL值當作一個Mem數據結構來處理,Vdbe——虛擬機數據結構 | |
vdbemem.c | 26375 | 操作”Mem”數據結構的函數 | |
vdbefifo.c | 2927 | ||
B-Tree部分 | btree.h | 5260 | 頭文件,定義了B-tree提供的操作接口 |
btree.c | 215570 | B-Tree部分的主要實現,並定義了以下數據結構:Btree——Btree handler,BtCursor——使用的游標, BtLock——鎖, BtShared——包含了一個打開的數據庫的所有信息,MemPage——文件在內存存放在該數據結構中,aCellInfo | |
OS Interface部分 | os.h | 18355 | 定義了為上層模塊提供的操作函數,並定義了以下數據結構: |
OsFile——描述一個文件 | |||
IoMethod——OsFile所支持的操作函數(對所有架構都適用的OS Interface) | |||
os.c | 2866 | 對IoMethod中的函數的包裝 | |
os_win.c | 42975 | Windows平台下的OS Interface | |
os_unix.c | 60831 | Unix平台下的OS Interface | |
os_os2.c | 28451 | OS2平台下的OS Interface | |
其它部分 | utf.c | 20891 | 與UTF編碼有關的函數 |
util.c | 43575 | 一些實用函數,比如: | |
sqlite3Malloc(),sqlite3FreeX() | |||
sqlite3.h | 63873 | SQLite的頭文件,定義了提供給應用使用的API和數據結構。 | |
sqliteInt.h | 78886 | 定義了SQLite內部使用的接口和數據結構 | |
printf.c | 29556 | 主要實現與printf有關的函數 | |
random.c | 3078 | 隨機數生成 | |
hash.c | 11896 | SQLite使用的hash表 | |
hash.h | 4033 | Hash 表頭文件 |