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

   

  在內部,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 表頭文件


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM