SQLite支援3種執行緒模式

2021-10-10 12:52:29 字數 3919 閱讀 7068

1、sqlite多執行緒使用總結----

2、關於多執行緒使用sqlite3的問題----

3、sqlite建立表成功,insert不報錯,但沒有資料插入----

4、sqlite3更新資料庫問題 sql執行成功但資料庫資料不改變----

5、sql(insert、delete、update)執行成功,但是資料庫表中無顯示無記錄----

6、使用事務,程式中sql語句都執行了,但是資料庫沒有變化----

1. 單執行緒:這種模式下,沒有進行互斥,多執行緒使用不安全。禁用所有的mutex鎖,併發使用時會出錯。當sqlite編譯時加了sqlite_threadsafe=0引數,或者在初始化sqlite前呼叫sqlite3_config(sqlite_config_singlethread)時啟用。

2. 多執行緒:這種模式下,只要乙個資料庫連線不被多個執行緒同時使用就是安全的。原始碼中是啟用bcoremutex,禁用bfullmutex。實際上就是禁用資料庫連線和prepared statement(準備好的語句)上的鎖,因此不能在多個執行緒中併發使用同乙個資料庫連線或prepared statement。當sqlite編譯時加了sqlite_threadsafe=2引數時預設啟用。若sqlite_threadsafe不為0,可以在初始化sqlite前,呼叫sqlite3_config(sqlite_config_multithread)啟用;或者在建立資料庫連線時,設定sqlite_open_nomutex flag。

3. 序列:sqlite是執行緒安全的。啟用所有的鎖,包括bcoremutex和bfullmutex 。因為資料庫連線和prepared statement都已加鎖,所以多執行緒使用這些物件時沒法併發,也就變成序列了。當sqlite編譯時加了sqlite_threadsafe =1引數時預設啟用。若sqlite_threadsafe不為0,可以在初始化sqlite前,呼叫sqlite3_config(sqlite_config_serialized)啟用;或者在建立資料庫連線時,設定sqlite_open_fullmutex flag  。

而這裡所說的初始化是指呼叫sqlite3_initialize()函式,這個函式在呼叫sqlite3_open()時會自動呼叫,且只有第一次呼叫是有效的。

csqlapi::csqlapi(tdbcfg *ptdbcfg)

配置執行緒模式

//描述:配置執行緒的對資料庫的併發訪問模式

//引數:@bmode 配置執行緒模式

// 1. sqlite_config_singlethread:單執行緒模式

// 2. sqlite_config_multithread:多執行緒模式

// 3. sqlite_config_serialized:序列模式

void csqlapi::configthreadmode(byte bmode)

else

}

開啟資料庫

void csqlapi::createdb(const char *pszdbpathfile)

//if ((iret=sqlite3_open(m_pdbc->pszdbname, &m_db)) != sqlite_ok)

if ((iret=sqlite3_open_v2(pszdbpathfile, &m_db, sqlite_open_readwrite | sqlite_open_create | sqlite_open_nomutex | sqlite_open_sharedcache, null)) != sqlite_ok)

printstr("csqlapi::createdb: error: %s\n", sqlite3_errstr(iret));

if (m_ptdbcfg->fensharecache)

execmd(__function__, "pragma read_uncommitted = true");

}

為了達到執行緒安全,sqlite在編譯時必須將 sqlite_threadsafe 預處理巨集置為1。在windows和linux上, 已編譯的好的二進位制發行版中都是這樣設定的。如果不確定你所使用的庫是否是執行緒安全的,可以呼叫 sqlite3_threadsafe() 介面找出。呼叫sqlite3_threadsafe()可以獲得編譯期的sqlite_threadsafe引數 。

//描述:獲取資料庫編譯時指定的執行緒模式

int csqlapi::getthreadmode()

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

編譯時選擇執行緒模式

可以通過定義sqlite_threadsafe巨集來指定執行緒模式。如果沒有指定,預設為序列模式。定義sqlite_threadsafe=1指定使用序列模式;=0使用單執行緒模式;=2使用多執行緒模式。

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

最後一句可通過sqlite3_threadsafe函式的實現來理解sqlite_api int sqlite3_threadsafe(void)如果編譯時指定了單執行緒模式,那麼臨界互斥邏輯在構造時就被省略,因此也就無法在啟動時或執行時指定序列模式或多執行緒模式。

啟動時選擇執行緒模式

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

執行時選擇執行緒模式

如果沒有在編譯時和啟動時指定為單執行緒模式,那麼每個資料庫連線在建立時可單獨的被指定為多執行緒模式或者序列模式,但是不能指定為單執行緒模式。如果在編譯時或啟動時指定為單執行緒模式,就無法在建立連線時指定多執行緒或者序列模式。

建立連線時用sqlite3_open_v2()函式的第三個引數來指定執行緒模式。sqlite_open_nomutex標識建立多執行緒模式的連線;sqlite_open_fullmutex標識建立序列模式的連線。如果沒有指定標識,或者使用sqlite3_open()或sqlite3_open16()函式來建立資料庫連線,那麼在編譯時或啟動時指定的執行緒模式將作為預設的執行緒模式使用。

void csqlapi::createdb(const char *pszdbpathfile)

在MFC中支援sqlite3

建立mfc工程的步驟我就不贅述了,以下操作均假設你已經建立好了乙個mfc工程 測試環境 windows7 編譯環境 visual studio 2015 新增步驟 2 解壓,將common 資料夾中的cppsqlite3.cpp cppsqlite3.h sqlite3.dll sqlite3.li...

執行緒通訊 3種方式

一 傳統執行緒通訊 synchronized wait notify object類的wait notify notifyall 三個方法必須由同步監視器物件來呼叫,分兩種情況 a 同步方法,該類預設例項 this 就是同步監視器,可以在同步方法中可以直接呼叫 b 同步 塊,同步監視器是synchr...

實現執行緒3種方式

1 繼承thread實現。2 實現runnable介面。3 實現callable介面,用futuretask接收返回值。總結 其實執行緒最核心的是runnable,因為thread和futuretask都繼承該介面來實現具體功能,即拓展實現。而thread實現的start0 方法,其呼叫本地方法開啟...