SQLite架構(gòu)

本文譯自《Architecture of SQLite》

介紹

這篇文檔描述了SQLite庫的架構(gòu)汛闸。如果想理解SQLite內(nèi)部原理,或者對它進(jìn)行修改,這篇文檔提供了有幫助的信息。

下圖展示了SQLite的主要組件和它們的協(xié)作方式粤策。后文解釋了這些組件的具體職責(zé)。

SQLite模塊

本文中各組件的原文譯文對照:

原文 譯文
Interface 接口
SQL Command Processor SQL命令處理器
Virtual Machine 虛擬機(jī)
Tokenizer 詞法分析器
Parser 語法分析器
B-Tree B樹
Pager 頁緩存
OS Interface OS接口
Utilities 通用庫
Test Code 測試代碼

概覽

SQLite的工作流程是將SQL文本編譯成字節(jié)碼误窖,然后在虛擬機(jī)上運(yùn)行這些字節(jié)碼叮盘。

sqlite3_prepare_v2()和相關(guān)的接口起到編譯器的作用,將SQL文本轉(zhuǎn)化為字節(jié)碼霹俺。sqlite3_stmt對象是一個字節(jié)碼容器柔吼,存儲了單條SQL語句所編譯出的字節(jié)碼。sqlite3_step()接口將字節(jié)碼程序傳給虛擬機(jī)吭服,執(zhí)行字節(jié)碼程序直到它完成嚷堡、返回結(jié)果集、遇到嚴(yán)重錯誤或被中斷(interrupted)艇棕。

接口

C語言接口主要在main.c蝌戒,legacy.cvdbeapi.c中,也有一些接口分散在其他文件中沼琉,這是為了使它們能使用一些文件私有的數(shù)據(jù)結(jié)構(gòu)北苟。sqlite3_get_table()例程在table.c中,sqlite3_mprintf()printf.c中打瘪,sqlite3_complete()tokenize.c中友鼻,TCL Interfacetclsqlite.c中傻昙。

為避免名稱沖突,SQLite庫中的所有外部符號都以前綴sqlite3開頭彩扔。那些用于外部使用的符號妆档,也就是出現(xiàn)在SQLite API中的符號,會添加一個下劃線虫碉,從而以sqlite3_開頭贾惦。擴(kuò)展API有時會在下劃線之前添加擴(kuò)展名,例如:sqlite3rbu_或sqlite3session_敦捧。

詞法分析器

當(dāng)一條SQL語句要被編譯時须板,它首先被發(fā)送給詞法分析器。

詞法分析器將SQL文本分解成詞兢卵,然后將它一個個交給語法分析器习瑰。詞法分析器的文件是tokenize.c,其中的代碼是手工寫的秽荤。

注意此處的設(shè)計甜奄,是詞法分析器調(diào)用語法分析器。熟悉YACC或者BISON的人可能習(xí)慣于反過來——讓語法分析器調(diào)用詞法分析器窃款。前者更好贺嫂,因?yàn)樗梢宰龅骄€程安全,并且運(yùn)行地更快雁乡。

語法分析器

語法分析器根據(jù)詞的上下文賦予它語義。

SQLite的語法分析器通過Lemon LALR(1)生成糜俗。Lemon的功能和YACC踱稍、BISON類似,但是它所使用的輸入語法更不容易出錯悠抹。同時Lemon生成的語法分析器是可重入和線程安全的珠月。Lemon定義了“非終結(jié)符析構(gòu)器(non-terminal destructor)”的概念,因此它在遇到語法錯誤時不會泄露內(nèi)存楔敌。Lemon所需的語法文件是parse.y啤挎,其中定義了SQLite使用的SQL語法。

因?yàn)長emon很可能不在開發(fā)機(jī)器上卵凑,它完整的源代碼在SQLite的tool文件夾中庆聘,僅有一個C文件。

代碼生成器

語法分析器將詞轉(zhuǎn)化為語法樹勺卢,代碼生成器分析語法樹伙判,并且生成符合SQL功能的字節(jié)碼。

prepared statement對象是這段字節(jié)碼的容器黑忱。代碼生成器包含很多文件:attach.c宴抚,** auth.c勒魔, build.cdelete.c菇曲,expr.c冠绢, insert.cpragma.c常潮,select.c弟胀,trigger.cupdate.c蕊玷,vacuum.c邮利,where.cwherecode.c以及whereexpr.c**垃帅。SQLite的魔法大多發(fā)生在這些文件中延届。

expr.c處理表達(dá)式的代碼生成,where.c處理SELECT贸诚,UPDATE方庭,DELETE語句的WHERE子句的代碼生成。attach.c酱固, delete.c械念,insert.cselect.c运悲,trigger.c龄减, update.c,和vacuum.c處理和文件名對應(yīng)的SQL語句的代碼生成班眯,其中每個文件都需要調(diào)用expr.cwhere.c中的例程希停。其他所有的SQL語句都由build.c處理。auth.c*實(shí)現(xiàn)了sqlite3_set_authorizer()的功能署隘。

代碼生成器宠能,特別是where.cselect.c中的邏輯部分,有時被稱作查詢計劃器query planner磁餐。對于任何一條SQL語句违崇,可能有成百上千種不同的算法能得出結(jié)果。查詢計劃器是一個AI诊霹,盡力從其中選出最好的算法羞延。

字節(jié)碼引擎

生成器輸出的代碼最終由虛擬機(jī)來執(zhí)行。

虛擬機(jī)本身完全包含在單個文件中脾还,即vdbe.c文件肴楷。vdbe.h頭文件定義了其他SQLite庫與虛擬機(jī)之間的接口,而vdbeInt.h定義了虛擬機(jī)私有的數(shù)據(jù)結(jié)構(gòu)和接口荠呐。

剩下的多個vdbe.c文件是虛擬機(jī)的輔助代碼赛蔫。vdbeaux.c文件包含了虛擬機(jī)使用的通用庫砂客,以及其他庫用來構(gòu)造VM程序的接口模塊。vdbeapi.c文件包含了虛擬機(jī)的外部接口呵恢,比如sqlite3_bind_int()sqlite3_step()鞠值。單個值(字符串,整數(shù)渗钉,浮點(diǎn)數(shù)彤恶,二進(jìn)制數(shù)據(jù))存儲在一個內(nèi)部對象“Mem”中,該對象在vdbemem.c*實(shí)現(xiàn)鳄橘。

SQLite通過回調(diào)C語言來實(shí)現(xiàn)SQL的函數(shù)声离。甚至內(nèi)置的SQL函數(shù)也通過這種方式實(shí)現(xiàn)。大部分內(nèi)置SQL函數(shù)瘫怜,例如abs()术徊, count()substr()等鲸湃,都寫在func.c文件中赠涮。日期時間轉(zhuǎn)換函數(shù)寫在date.c中。一些函數(shù)暗挑,例如coalesce()typeof()直接被代碼生成器實(shí)現(xiàn)為字節(jié)碼笋除。

B樹

SQLite使用B樹結(jié)構(gòu)來維護(hù)磁盤上的數(shù)據(jù),B樹的實(shí)現(xiàn)在btree.c文件中炸裆。

數(shù)據(jù)庫中每個表和索引都使用單獨(dú)的B樹垃它。全部的B樹都存儲在同一個磁盤文件中。文件格式的規(guī)格是明確且穩(wěn)定的烹看,并且保證向前兼容嗤瞎。

B樹子系統(tǒng)對其他SQLite庫的接口定義在頭文件btree.h中。

頁緩存

B樹模塊要求磁盤上的信息具有固定的頁面大小听系。默認(rèn)的頁面大小(page_size)是4096字節(jié)虹菲,但是也可以設(shè)置為512到65536之間的2的整數(shù)冪靠胜。頁緩存負(fù)責(zé)頁面的讀寫和緩存。頁緩存也提供回滾和原子性提交的抽象毕源,并且負(fù)責(zé)對數(shù)據(jù)庫文件加鎖浪漠。

B樹模塊向頁緩存請求頁面,并且在修改頁面霎褐,提交或回滾時通知頁緩存址愿。頁緩存會處理大量的細(xì)節(jié),以確保請求被快速冻璃,安全响谓,高效地處理损合。

主要的頁緩存實(shí)現(xiàn)是在pager.c文件中,WAL模式的邏輯在單獨(dú)的wal.c中娘纷,內(nèi)存型緩存實(shí)現(xiàn)在pcache.cpcache1.c文件中嫁审。頁緩存子系統(tǒng)對其他SQLite庫的接口定義在pager.h中。

OS接口

為了提供跨操作系統(tǒng)移植性赖晶,SQLite使用名為VFS的抽象對象律适。每個VFS提供對磁盤文件的打開、關(guān)閉以及讀寫方法遏插,以及其他特定于操作系統(tǒng)的功能捂贿,如獲得當(dāng)前時間,為偽隨機(jī)數(shù)生成器設(shè)置隨機(jī)種子等胳嘲。

SQLite目前對unix和Windows提供VFS厂僧,分別在os_unix.cos_win.c文件中。

通用類

內(nèi)存分配胎围,大小寫不敏感的字符串比較例程吁系,可移植的字符串到數(shù)字轉(zhuǎn)換例程,以及其他通用庫位于util.c中白魂。

hash.c實(shí)現(xiàn)了哈希表結(jié)構(gòu)汽纤,在語法解析器中被用作符號表。utf.c源文件包含Unicode轉(zhuǎn)換的相關(guān)例程福荸。在printf.c中蕴坪,SQLite實(shí)現(xiàn)了自己私有的printf(),包含了一些拓展敬锐。在random.c中背传,SQLite也實(shí)現(xiàn)了自己的偽隨機(jī)數(shù)生成器。

測試代碼

在src文件夾中台夺,以test開頭的文件為測試代碼径玖,不被包含在標(biāo)準(zhǔn)庫版本中。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末颤介,一起剝皮案震驚了整個濱河市梳星,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌滚朵,老刑警劉巖冤灾,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異辕近,居然都是意外死亡韵吨,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進(jìn)店門移宅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來归粉,“玉大人椿疗,你說我怎么就攤上這事≌到剑” “怎么了变丧?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長绢掰。 經(jīng)常有香客問我痒蓬,道長,這世上最難降的妖魔是什么滴劲? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任攻晒,我火速辦了婚禮,結(jié)果婚禮上班挖,老公的妹妹穿的比我還像新娘鲁捏。我一直安慰自己,他們只是感情好萧芙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布给梅。 她就那樣靜靜地躺著,像睡著了一般双揪。 火紅的嫁衣襯著肌膚如雪动羽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天渔期,我揣著相機(jī)與錄音运吓,去河邊找鬼。 笑死疯趟,一個胖子當(dāng)著我的面吹牛拘哨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播信峻,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼倦青,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了盹舞?” 一聲冷哼從身側(cè)響起产镐,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎矾策,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體峭沦,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贾虽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了吼鱼。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蓬豁。...
    茶點(diǎn)故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡绰咽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出地粪,到底是詐尸還是另有隱情取募,我是刑警寧澤,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布蟆技,位于F島的核電站玩敏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏质礼。R本人自食惡果不足惜旺聚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望眶蕉。 院中可真熱鬧砰粹,春花似錦、人聲如沸造挽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽饭入。三九已至嵌器,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間圣拄,已是汗流浹背嘴秸。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留庇谆,地道東北人岳掐。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像饭耳,于是被迫代替她去往敵國和親串述。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評論 2 349

推薦閱讀更多精彩內(nèi)容