標籤:
API
分為兩大類
- core API. 基本的SQL操作
- extension API. 建立自訂的SQL操作。
基本資料結構
需要瞭解的組成部分有串連、statments、B樹、pager。
為了寫好SQLite代碼,需要瞭解的基本概念,API、事務和鎖。
串連和statments
這兩種資料結構和查詢語句的基礎。一個串連表示對資料庫的一個串連,也是一個事務上下文。statments由這些串連產生。statments在內部由VDBE位元組碼錶示。
B-tree and pager
每個資料庫連接可以有多個資料庫。每一個資料庫物件有一個B-tree對象,每一個B-tree對象有一個pager對象。
pager的工作包括把page從磁碟匯入到記憶體中、寫資料庫、管理事務、處理鎖和從crash中恢複等。
一個資料庫連接中是在事務中操作,一個資料庫連接不會同時有兩個事務。
Core API
兩種方式來執行SQL語句。
- prepared query. SQLite執行命令的最終方式。包括三個階段
- preparation
- execution
- finalization
- wrapped query
串連資料庫
sqlite3_open()
傳入:memory:
或Null 字元串作為資料庫的名稱,會建立記憶體中的資料庫。
如果資料庫的pagesize和作業系統的pagesize相同,會提高IO效率。
運行prepared query
- prepation:把字串轉化為VDBE位元組碼。
sqlite3_prepare_v2()
產生sqlite3_stmt
控制代碼,包括編譯好的位元組碼和需要執行命令和迭代結果集的所有資源。
- execution:
sqlite3_step
使VDBE逐步執行位元組碼。首次調用會擷取某種鎖。
- finalization:
sqlite3_finalize()
關閉statment,釋放相關資源。
使用參數化的SQL
包括兩種參數綁定
- positional
- named
使用參數綁定的優勢
- 不需要編譯,可以執行statment多次。只需要reset,然後重新bind,運行。
- 自動處理好逸出字元,避免資料庫注入和語法錯誤。
運行wrapped query
sqlite3_exec()
和sqlite3_get_table()
exec()
解析命令,識別出單獨的語句,並依次處理。
處理錯誤
sqlite3_errcode()
返回最後執行函數的錯誤碼。使用sqlite3_errmsg()
提供最後錯誤的描述。
格式化SQL語句
sqlite3_mprintf()
.類似sprintf()
,%q
和%s
類似,不過會把每一個單引號變為連續的兩個,防止資料庫注入。%Q
會為字串首尾加上單引號,null 指標會變成NULL
操作控制
使用註冊filter或callback函數來達到在特定事件發生時會被monitor,control。
有三個hook函數
sqlite3_commit_hook()
sqlite3_rollback_hook()
sqlite3_update_hook()
wal_hook()
(3.7版本中)
使用多線程
shared cache mode:使用多個一個線程來管理多個SQL串連,這些串連共用page cache,降低了server的記憶體使用量。
extension API事務事務的生命週期
- 在事務下究竟是什麼在運行。
在每個資料連線中的每個資料庫物件,有一個B-Tree和pager對象。pager管理事務、鎖、緩衝、崩潰恢複。
- 事務何時開始,何時結束,何時開始影響其他資料庫連接。
可以短到一個語句,可以長到直到你命令終結。一個操作預設在autocommit模式,即每一個命令在一個事務中運行。何時影響和鎖的狀態有關。###鎖的狀態每一個事務以unlocked
,reserved
,exclusize
鎖狀態開始
讀事務
兩次讀操作
使用事務:unlocked->pending->shared->unlocked
不使用事務:unlocked->pending->shared->unlocked->pending->shared->unlocked
不適用事務,在兩次讀之間資料可能會改變
寫事務
每一個操作,讀或者寫,都必須經過unlocked->pending->shared. pending是gateway lock。
reserved state
當要向資料庫中寫入時,需要從shared到reserved狀態。到reserved狀態後,可以把改變寫到本機快取,而不是資料庫中。
進入reserved狀態後,pager初始化rollback journal,是用於復原和crash recovery的檔案。實際是為更改前的資料庫內容。
在reserved狀態中,需要pager維護三種pages:改變的pages(存在page cache中),未改變的pages(讀出的沒有改變的page)以及日誌pages(不在page cache中,而是在B-Tree改變page前寫入joural)。
pending state
pending lock是gateway lock,保證不會有鎖從unlocked到shared狀態。
exclusive state
此狀態下,主要工作是把改變的page從page cache沖入資料庫檔案。此時pager真正開始改變資料庫。
在寫入資料庫之前,先確保記錄檔已經被寫入磁碟。
日誌是系統崩潰或掉電後,日誌是恢複資料庫的唯一方法。
記錄檔在commit之後才會被清除。
自動認可和效率
自動認可效率不高,因為每個語句都要擷取鎖。而且語句之間可能會被改變。
調整page cache轉向互斥狀態
一般來說,當pager不能儲存更多資料時,會從reserved狀態轉向互斥狀態。實際上,有soft limit和hard limit。
soft limit是指page cache首次被佔滿,此時包括改變的和未更改page的混合。pager會移除未更改的page,如此重複,直到所有的都被更改的page佔滿。此時page cache都是已更改的page,進入hard limit,不得不轉向互斥狀態。
cache_size
調整page cache的大小。
決定page cache的大小
利用sqlite3_analyer
等待鎖使用busy handler
sqlite3_busy_timeout()
使用正確的事務
寫操作使用begin immediate
SQLite Design and Concepts