1. 程式人生 > >Sqlite3多執行緒讀寫解決方案

Sqlite3多執行緒讀寫解決方案

原標題:SQLite And Multiple Threads

SQLite 支援三種執行緒模式:
1. 單執行緒模式
    這種模式下,沒有進行互斥,多執行緒使用不安全
2. 多執行緒模式
    這種模式下,在多執行緒中使用單個資料庫連線是不安全的,否則就是安全的。譯註:即不能在多個執行緒中共享資料庫連線)
3. 序列模式
    這種模式下,sqlite是執行緒安全的(譯註:即使在多個執行緒中不加互斥的使用同一個資料庫連線)

    執行緒模式可以在編譯時(通過原始碼編譯sqlite庫時)、啟動時(使用sqlite的應用程式初始化時)或者執行時(建立資料庫連線時)來指定。一般而言,執行時指定的模式將覆蓋啟動時的指定模式,啟動時指定的模式將覆蓋編譯時指定的模式。但是,單執行緒模式一旦被指定,將無法被覆蓋。
    預設的執行緒模式是序列模式。

編譯時選擇執行緒模式
    可以通過定義SQLITE_THREADSAFE巨集來指定執行緒模式。

定義巨集SQLITE_THREADSAFE=1指定使用序列模式;

SQLITE_THREADSAFE=0使用單執行緒模式;

SQLITE_THREADSAFE=2使用多執行緒模式。

如果沒有指定,預設為序列模式。


    sqlite3_threadsafe()函式的返回值可以確定編譯時指定的執行緒模式。如果指定了單執行緒模式,函式返回false。如果指定了序列或者多執行緒模式,函式返回true。由於sqlite3_threadsafe()函式要早於多執行緒模式以及啟動時和執行時的模式選擇,所以它既不能區別多執行緒模式和序列模式也不能區別啟動時和執行時的模式。

譯註:最後一句可通過sqlite3_threadsafe函式的實現來理解
SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }

    如果編譯時指定了單執行緒模式,那麼臨界互斥邏輯在構造時就被省略,因此也就無法在啟動時或執行時指定序列模式或多執行緒模式。

啟動時選擇執行緒模式
    假如在編譯時沒有指定單執行緒模式,就可以在應用程式初始化時使用sqlite3_config()函式修改執行緒模式。引數SQLITE_CONFIG_SINGLETHREAD可指定為單執行緒模式,SQLITE_CONFIG_MULTITHREAD指定為多執行緒模式,SQLITE_CONFIG_SERIALIZED指定為序列模式。

執行時選擇執行緒模式
    如果沒有在編譯時和啟動時指定為單執行緒模式,那麼每個資料庫連線在建立時可單獨的被指定為多執行緒模式或者序列模式,但是不能指定為單執行緒模式。如果在編譯時或啟動時指定為單執行緒模式,就無法在建立連線時指定多執行緒或者序列模式。
    建立連線時用sqlite3_open_v2()函式的第三個引數來指定執行緒模式。SQLITE_OPEN_NOMUTEX標識建立多執行緒模式的連線;SQLITE_OPEN_FULLMUTEX標識建立序列模式的連線。如果沒有指定標識,或者使用sqlite3_open()或sqlite3_open16()函式來建立資料庫連線,那麼在編譯時或啟動時指定的執行緒模式將作為預設的執行緒模式使用。