2011-08-19 294 views
3

我有一段C++中的代碼,它創建了很多線程&這些線程中的每一個都訪問一個常見的SQLite數據庫& SELECTs & INSERTs data。SQLite數據庫被鎖定

所有INSERT都處於事務中。很多時候,我收到「數據庫已鎖定」錯誤。

我該如何解決這個問題?

回答

7

可以使用SQLite在多線程的方式,但對於每一個線程,你必須打開一個新的連接(sqlite3_open())和連接上的操作。

有一個在official documentation

+0

很棒!謝謝! – omggs

0

我主要試圖指出,正如一些人認爲的,你不應該讓多個用戶寫入相同的SQLite數據庫,因爲這不是它的設計目的;

(5)多個應用程序或同一個應用程序的多個實例可以同時訪問單個數據庫文件嗎?

多個進程可以同時打開同一個數據庫。 多個進程可以同時做一個SELECT。但是,只有 一個進程可以在 的任何時刻對數據庫進行更改。

SQLite使用讀寫器鎖來控制對數據庫的訪問。 (在Win95/98/ME中,缺少對讀寫器鎖定的支持,而是使用概率模擬代替 )。但請注意:如果數據庫文件保留在NFS文件系統上,則此鎖定機制可能無法正常工作。這是因爲fcntl()文件鎖定在許多NFS實現上破壞了 。如果多個進程可能嘗試同時訪問 文件,則應避免將SQLite 數據庫文件放在NFS上。在Windows上,Microsoft的文檔說如果您沒有運行 Share.exe守護進程, 鎖定可能無法在FAT文件系統下工作。對Windows 有很多經驗的人告訴我,網絡文件的文件鎖定非常麻煩,並且不是 可靠的。如果他們說的是真的,在兩臺或多臺Windows機器之間共享SQLite數據庫 可能會導致意外問題。

我們意識到沒有其他嵌入式SQL數據庫引擎可以像SQLite那樣支持很多併發性,如 。 SQLite允許多個進程一次打開數據庫文件,並允許多個進程一次讀取數據庫 。當任何進程想要寫入時,它必須在整個數據庫文件更新期間鎖定整個數據庫文件。但通常 只需要幾毫秒。其他進程只需等待作者 完成,然後繼續他們的業務。其他嵌入式SQL數據庫引擎通常只允許單個進程一次連接到數據庫。

然而,客戶機/服務器數據庫引擎(如PostgreSQL的,MySQL和或 甲骨文)通常支持併發的更高水平,並允許 多個進程在同一 時間被寫入到相同的數據庫。這在客戶端/服務器數據庫中是可能的,因爲總是有一個良好控制的服務器進程可用來協調 訪問。如果您的應用程序需要很多併發性,那麼您應該考慮使用客戶機/服務器數據庫。但是經驗 表明,大多數應用程序所需要的併發性比設計者想象的要少得多。

當SQLite試圖訪問被另一進程鎖定的文件時, 的默認行爲是返回SQLITE_BUSY。您可以使用sqlite3_busy_handler()或sqlite3_busy_timeout()API函數從C代碼 調整這個 行爲。

來源:http://www.sqlite.org/faq.html

+1

假的,它使用多線程/ multiconnection。請參閱http://www.sqlite.org/threadsafe.html –

+0

我更新了,對不起 – Coops

2

更多信息。如果你開始你的交易只對一個多線程的「開始」,然後您正在使用的INSERT源碼可以死鎖。

這是因爲只有源碼上aquires開始讀鎖。在INSERT上,它必須將讀鎖升級到寫鎖(只有在沒有讀鎖的情況下才能執行)。 隨着wal模式在寫入期間允許讀取訪問,journal_mode = WAL(僅默認journal_mode = delete)時不會發生這種情況。 (所以使用WAL模式可能是一個解決方法)。

解決方案:使用 立刻開始,如果你打算在交易中使用的刀片。這樣sqlite獲得數據庫的寫入鎖定。