SQLite剖析之體系結構

1.經過官方的SQLite架構文檔,理清大致的系統層次: Architecture of SQLite
2.閱讀 SQLite Documentation中Technical/Design Documentation章節(根據所在層次閱讀代碼,對應章節描述進行理解。)
應用層角度,從API(List Of SQLite Functions)角度切入,掌握API文檔中全部參數的使用。
3.下載源碼包sqlite-src-*.zip,在其src目錄下包含了全部源碼文件。注意若要編譯SQLite庫則下載單一文件版本sqlite-amalgamation-*.zip。

架構(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的主要組件以及各組件之間是如何相互關聯的。html

   

  在內部,SQLite由如下幾個組件組成:內核、SQL編譯器、後端以及附件。SQLite經過利用虛擬機和虛擬數據庫引擎(VDBE),使調試、修改和擴展SQLite的內核變得更加方便。全部SQL語句都被編譯成易讀的、能夠在SQLite虛擬機中執行的程序集。SQLite支持大小高達2 TB的數據庫,每一個數據庫徹底存儲在單個磁盤文件中。這些磁盤文件能夠在不一樣字節順序的計算機之間移動。這些數據以B+樹(B+tree)數據結構的形式存儲在磁盤上。SQLite根據該文件系統得到其數據庫權限。sql

一、公共接口(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_開頭來命名的。數據庫

二、詞法分析器(Tokenizer)
    當執行一個包含SQL語句的字符串時,接口程序要把這個字符串傳遞給tokenizer。Tokenizer的任務是把原有字符串分割成一個個標識符(token),並把這些標識符傳遞給解析器。Tokenizer是用手工編寫的,在C文件tokenize.c中。
    在這個設計中須要注意的一點是,tokenizer調用parser。熟悉YACC和BISON的人們也許會習慣於用parser調用tokenizer。SQLite的做者已經嘗試了這兩種方法,並發現用tokenizer調用parser會使程序運行的更好。YACC會使程序更滯後一些。後端

三、語法分析器(Parser)api

    語法分析器的工做是在指定的上下文中賦予標識符具體的含義。SQLite的語法分析器使用Lemon LALR(1)分析程序生成器來產生,Lemon作的工做與YACC/BISON相同,但它使用不一樣的輸入句法,這種句法更不易出錯。Lemon還產生可重入的而且線程安全的語法分析器。Lemon定義了非終結析構器的概念,當遇到語法錯誤時它不會泄露內存。驅動Lemon的源文件可在parse.y中找到。
    由於lemon是一個在開發機器上不常見的程序,因此lemon的源代碼(只是一個C文件)被放在SQLite的"tool"子目錄下。 lemon的文檔放在"doc"子目錄下。緩存

四、代碼生成器(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()的功能。數據結構

五、虛擬機(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中找到。併發

六、B-樹(B-Tree)
    一個SQLite數據庫使用B-樹的形式存儲在磁盤上,B-樹的實現位於源文件btree.c中。數據庫中的每一個表和索引使用一棵單獨的B-樹,全部的B-樹存放在同一個磁盤文件中。文件格式的細節被記錄在btree.c開頭的備註裏。B-樹子系統的接口在頭文件btree.h中定義。

七、頁面高速緩存(Page Cache)
    B-樹模塊以固定大小的數據塊形式從磁盤上請求信息,默認的塊大小是1024個字節,可是能夠在512和65536個字節之間變化。頁面高速緩存負責讀、寫和緩存這些數據塊。頁面高速緩存還提供回滾和原子提交的抽象,而且管理數據文件的鎖定。B-樹驅動模塊從頁面高速緩存中請求特定的頁,當它想修改頁面、想提交或回滾當前修改時,它也會通知頁面高速緩存。頁面高速緩存處理全部麻煩的細節,以確保請求可以快速、安全而有效地被處理。
    頁面高速緩存的代碼實現被包含在單一的C源文件pager.c中。頁面高速緩存子系統的接口在頭文件pager.h中定義。

八、OS接口
    爲了在POSIX和Win32操做系統之間提供移植性,SQLite使用一個抽象層來提供操做系統接口。OS抽象層的接口在os.h中定義,每種支持的操做系統有各自的實現:Unix使用os_unix.c,Windows使用os_win.c,等等。每一個特定操做系統的實現一般都有本身的頭文件,如os_unix.h, os_win.h等。

九、實用工具(Utilities)
    內存分配和字符串比較函數位於util.c中。語法分析器使用的符號表用Hash表來維護,其實現位於hash.c中。源文件utf.c包含Unicode轉換子程序。SQLite有本身的printf()實現(帶一些擴展功能),在printf.c中,還有本身的隨機數生成器,在random.c中。

十、測試代碼(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 表頭文件
相關文章
相關標籤/搜索