sqlite3 多線程問題...(轉載)

7) 多個應用程序或者同一個應用程序的多個例程能同時存取同一個數據庫文件嗎?

多進程可以同時打開同一個數據庫,也可以同時 SELECT 。但只有一個進程可以立即改數據庫。

SQLite使用讀/寫鎖定來控制數據庫訪問。(Win95/98/ME 操作系統缺乏讀/寫鎖定支持,在低於 2.7.0 的版本中,這意味着在 windows 下在同一時間內只能有一個進程讀數據庫。在版本 2.7.0 中 這個問題通過在 windows 接口代碼中執行一個用戶間隔機率讀寫鎖定策略解決了。) 但如果數據庫文件在一個 NFS 文件系統中,控制併發讀書的鎖定機制可以會出錯。因爲 NFS 的fcntl() 文件鎖定有時會出問題。如果有多進程可能併發讀數據庫則因當避免把數據庫文件放在 NFS 文件系統中。 根據微軟的文檔,如果不運行 Share.exe 後臺程序則 FAT 文件系統中的鎖定可能不工作。對 Windows 非常有經驗的人告訴我網絡文件的鎖定有許多問題並且不可靠。如果是這樣,在2個或以上 Windows 系統中共享一個 SQLite 數據庫文件會導致不可預知的問題。

我們知道沒有其他的嵌入式 SQL數據庫引擎比SQLite支持更多的併發性。 SQLite允許多進程 同時打開和讀取數據庫。任何一個進程需要寫入時,整個數據庫將在這一過程中被鎖定。但這一般僅耗時 幾毫秒。其他進程只需等待然後繼續其他事務。其他嵌入式SQL數據庫引擎往往只允許單進程訪問數據庫。

但是,client/server型的數據庫引擎 (如 PostgreSQL, MySQL, 以及 Oracle) 通常支持更高的併發度, 並支持多進程同時寫入同一個數據庫。由於總有一個控制良好的服務器協調數據庫的訪問,這才保證了以上 特性的實現。如果你的應用需要很高的併發度,你應該考慮使用client/server數據庫。事實上,經驗告訴 我們大多數應用所需要的併發度比他們的設計者們想象的要少得多。

當 SQLite 嘗試操作一個被另一個進程鎖定的文件時,缺省的行爲是返回 SQLITE_BUSY。你可以用 C代碼更改這一行爲。 使用 sqlite3_busy_handler() 或sqlite3_busy_timeout() API函數。

如果兩個或更多進程同時打開同一個數據庫,其中一個進程創建了新的表或索引,則其它進程可能不能立即看見新的表。其它進程可能需要關閉並重新連結數據庫。


--------------------------------------------------------------------------------

(8) SQLite是線程安全的嗎?

有時候是的。爲了線程安全,SQLite 必須在編譯時把 THREADSAFE 預處理宏設爲1。在缺省的發行的已編譯版本中 Windows 版的是線程安全的,而 Linux 版的不是。如果要求線程安全,Linux 版的要重新編譯。

“線程安全”是指二個或三個線程可以同時調用獨立的不同的sqlite3_open() 返回的"sqlite3"結構。而不是在多線程中同時使用同一個 sqlite3 結構指針。

一個sqlite3結構只能在調用 sqlite3_open創建它的那個進程中使用。你不能在一個線程中打開一個數據庫然後把指針傳遞給另一個線程使用。這是因爲大多數多線程系統的限制(或 Bugs?)例如RedHat9上。在這些有問題的系統上,一個 線程創建的fcntl()鎖不能由另一個線程刪除或修改。由於SQLite依賴fcntl()鎖來進行併發控制,當在線程間傳遞數據庫連接時會出現嚴重的問題。

也許在Linux下有辦法解決fcntl()鎖的問題,但那十分複雜並且對於正確性的測試將是極度困難的。因此,SQLite目前不允許在線程間共享句柄。

在UNIX下,你不能通過一個 fork() 系統調用把一個打開的 SQLite 數據庫放入子過程中,否則會出錯。

 

在多線程情況下,一個sqlite3句柄不能共享給多個線程使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章