從 版本 3.3.0 (2006-01-11) 開始,SQLite 包含一個特殊的「共享快取」模式(預設停用),供嵌入式伺服器使用。如果啟用共享快取模式,且執行緒建立多個連線至同一個資料庫,這些連線會共用單一資料和架構快取。這可以大幅減少系統所需的記憶體和 I/O 量。
在 版本 3.5.0 (2007-09-04) 中,共享快取模式已修改,讓同一個快取可以在整個處理程序中共用,而不再僅限於單一執行緒。在這個變更之前,在執行緒之間傳遞資料庫連線時有某些限制。這些限制已在 3.5.0 更新中移除。本文件說明版本 3.5.0 的共享快取模式。
在某些情況下,共享快取模式會變更鎖定模型的語意。本文件會說明詳細資訊。假設您已基本了解正常的 SQLite 鎖定模型(請參閱 SQLite 版本 3 中的檔案鎖定和並行處理 以取得詳細資訊)。
共享快取模式是一個過時的特色。不建議使用共享快取模式。大多數共享快取的使用案例都更適合 WAL 模式。
共享快取模式於 2006 年應 Symbian 開發人員的要求而發明。他們的問題是,如果手機上的連絡人資料庫正在同步,資料庫檔案就會被鎖定。然後,如果來電,資料庫鎖定會阻止他們查詢連絡人資料庫以尋找來電的適當鈴聲或要顯示在螢幕上的來電者照片,等等。WAL 模式(約 2010 年)是解決此問題的更好方法,因為它允許同時存取而不會中斷交易隔離。
建議從原始碼建置自己 SQLite 副本的應用程式使用 -DSQLITE_OMIT_SHARED_CACHE 編譯時間選項,因為產生的二進位檔案將更小且更快速。
這裡所述的共享快取介面將持續在 SQLite 中受到支援,以確保完全的向下相容性。但是,不建議使用共享快取。
從外部來看,從另一個處理程序或執行緒的角度來看,使用共享快取的兩個或多個 資料庫連線 顯示為單一連線。用於在多個共享快取或一般資料庫使用者之間仲裁的鎖定協定在其他地方有說明。
![]() |
圖 1
圖 1 說明一個範例執行時間組態,其中已建立三個資料庫連線。連線 1 是正常的 SQLite 資料庫連線。連線 2 和 3 共享一個快取。一般的鎖定協定用於在連線 1 和共享快取之間序列化資料庫存取。用於序列化(或不序列化,請參閱下方的「未提交讀取隔離模式」)連線 2 和 3 對共享快取的存取的內部協定在本節的其餘部分中說明。
共享快取鎖定模式有三個層級,交易層級鎖定、表格層級鎖定和架構層級鎖定。以下三個小節會說明這些層級。
SQLite 連線可以開啟兩種交易,讀取交易和寫入交易。這不是明確執行的,交易在第一次寫入資料庫表格之前,會隱含地成為讀取交易,在這個時間點會變成寫入交易。
在任何時間點,最多只有一個連線到單一共享快取可以開啟寫入交易。這可以與任意數量的讀取交易共存。
當兩個或多個連線使用共享快取時,鎖定會用來序列化每個表格的同時存取嘗試。表格支援兩種鎖定類型,「讀取鎖定」和「寫入鎖定」。鎖定會授予連線 - 在任何時間點,每個資料庫連線在每個資料庫表格上都有讀取鎖定、寫入鎖定或沒有鎖定。
在任何時間點,單一表格可以有任意數量的活動讀取鎖定或單一活動寫入鎖定。若要從表格讀取資料,連線必須先取得讀取鎖定。若要寫入表格,連線必須取得該表格的寫入鎖定。如果無法取得所需的表格鎖定,查詢會失敗,且會傳回 SQLITE_LOCKED 給呼叫者。
當連線取得表格鎖定後,在目前的交易 (讀取或寫入) 結束之前,不會釋放鎖定。
上述行為可以透過使用 read_uncommitted pragma,將隔離層級從序列化 (預設值) 變更為讀取未提交,來稍加修改。
未提交讀取模式的資料庫連線不會在從資料庫表格讀取前嘗試取得讀取鎖,如上所述。如果另一個資料庫連線在讀取時修改表格,這可能會導致不一致的查詢結果,但也表示未提交讀取模式連線開啟的讀取交易不會封鎖或被任何其他連線封鎖。
未提交讀取模式對寫入資料庫表格所需的鎖沒有影響(即未提交讀取連線仍必須取得寫入鎖,因此資料庫寫入仍可能封鎖或被封鎖)。此外,未提交讀取模式對下列規則所列舉的sqlite_schema鎖沒有影響(請參閱「架構(sqlite_schema)層級鎖定」章節)。
/* Set the value of the read-uncommitted flag: ** ** True -> Set the connection to read-uncommitted mode. ** False -> Set the connection to serialized (the default) mode. */ PRAGMA read_uncommitted = <boolean>; /* Retrieve the current value of the read-uncommitted flag */ PRAGMA read_uncommitted;
sqlite_schema 表格支援共享快取讀取和寫入鎖,方式與所有其他資料庫表格相同(請參閱上述說明)。下列特殊規則也適用
在 SQLite 版本 3.3.0 至 3.4.2 中,當啟用共享快取模式時,資料庫連線只能由呼叫sqlite3_open()建立它的執行緒使用。而且連線只能與同一個執行緒中的另一個連線共享快取。這些限制從 SQLite版本 3.5.0(2007-09-04)開始取消。
在較舊版本的 SQLite 中,共享快取模式無法與虛擬表格一起使用。此限制已在 SQLite 3.6.17 版本(2009-08-10)中移除。
共享快取模式會在每個處理程序的基礎上啟用。使用 C 介面,下列 API 可用於在全域啟用或停用共享快取模式
int sqlite3_enable_shared_cache(int);
每次呼叫 sqlite3_enable_shared_cache() 都會影響使用 sqlite3_open()、sqlite3_open16() 或 sqlite3_open_v2() 建立的後續資料庫連線。現有的資料庫連線不受影響。每個呼叫 sqlite3_enable_shared_cache() 都會覆寫同一個處理程序中所有先前的呼叫。
使用 sqlite3_open_v2() 建立的個別資料庫連線,可以使用第三個參數的 SQLITE_OPEN_SHAREDCACHE 或 SQLITE_OPEN_PRIVATECACHE 旗標,選擇是否參與共享快取模式。使用其中任一旗標都會覆寫 sqlite3_enable_shared_cache() 所建立的全球共享快取模式設定。不應使用超過一個旗標;如果在 sqlite3_open_v2() 的第三個參數中同時使用 SQLITE_OPEN_SHAREDCACHE 和 SQLITE_OPEN_PRIVATECACHE 旗標,則行為未定義。
當使用 URI 檔名 時,可以使用「快取」查詢參數指定資料庫是否會使用共享快取。使用「快取=共享」啟用共享快取,使用「快取=私人」停用共享快取。使用 URI 查詢參數指定資料庫連線的快取共用行為的功能,允許在 ATTACH 陳述式中控制快取共用。例如
ATTACH 'file:aux.db?cache=shared' AS aux;
從 SQLite 版本 3.7.13(2012-06-11)開始,只要資料庫使用 URI 檔案名稱 建立,就可以在 記憶體中資料庫 上使用共用快取。為了向後相容,如果使用未加修飾的名稱「:memory:」開啟資料庫,則記憶體中資料庫的共用快取始終會停用。在版本 3.7.13 之前,不論使用什麼資料庫名稱、目前的系統共用快取設定、查詢參數或旗標,記憶體中資料庫的共用快取始終都會停用。
為記憶體中資料庫啟用共用快取,可以讓同一個程序中的兩個或多個資料庫連線存取同一個記憶體中資料庫。共用快取中的記憶體中資料庫會自動刪除,且在最後一個連線到該資料庫關閉時會回收記憶體。
此頁面最後修改於 2023-01-02 14:22:42 UTC