2011-11-03 40 views
8

我想從2個不同的線程訪問SQLite數據庫,從而使用2個不同的連接到數據庫。這兩個線程將主要執行從數據庫中讀取數據,並且僅偶爾寫入數據庫。如果我覺得這兩個線程同時針對數據庫寫入數據的可能性,我應該感到安全嗎?在這種情況下,我不應該有任何問題?SQLite連接和鎖定

回答

6

SQLite是線程安全的,最近的版本中,你可以線程之間共享一個連接。也就是說,SQLite FAQ指出「線程是邪惡的」(我不認爲它們是指SQLite中的這種情況,而是一般性聲明)。

SQLite具有鎖定機制,因此即使第二個實例試圖獲取數據庫上的寫入鎖定,它也會排隊等待現有鎖定完成,因此即使兩個線程正在編寫SQLite也應該適應您。常見問題表明,使用不同進程的多個連接網絡文件系統通常是不安全的,因爲在文件系統中執行的鎖定效果不佳,但我認爲該警告不適用於您的使用。

+0

謝謝... FAQ是一個很好的資源 –

+0

但我想一個連接將不會有任何併發​​請求數據庫,而在@DrakeAmara的情況下,這將是偉大的,如果他有單獨的連接,因爲這意味着併發訪問數據庫 – user1530779

0

SQLite顯式不是線程安全的,因此如果你這樣做,你可以預期數據損壞。

使用互斥鎖確保兩個線程無法同時訪問數據庫,或花費數小時試圖追蹤很少發生且難以重現的幻影數據損壞錯誤。

http://sqlite.org/faq.html#q5

+4

從文檔(http://www.sqlite.org/faq.html# q6):** SQLite是線程安全的** –

9

不完全正確。請在這裏看到我的長回覆:

What are the best practices for SQLite on Android?

你不會損壞你的數據庫,但如果兩個不同的線程,有兩個不同的連接方式,試圖在同一時間寫的分貝,你將有問題。一個會「失去」。他們不會等待按順序運行。如果你調用'insert'而不是'insertOrThrow',你甚至不會得到異常。你只是不會寫入數據庫。

以下是Android中的Sqlite的工作原理。每個SqliteOpenHelper實例都有1個到數據庫的連接。無論您多次調用「getRead/WriteableDatabase」,都無關緊要。一個幫手,一個連接。另外,Android的sqlite連接代碼實現了自己的線程鎖定,所以如果你使用相同的SqliteOpenHelper,並通過擴展,相同的連接,你會沒事的。

但是,如果您使用多個助手,則可能會出現問題。

我懷疑你可以有多個線程閱讀,1個寫作,出來OK,但我沒有測試過這個。

您是否使用多個線程來提高寫入性能?如果是這樣,我會建議簡單地優化您對「交易」的使用。如果你做了多個獨立寫入,它非常慢。如果你把它們全部包裝在一起,它非常快(相對)。我懷疑這是因爲每次獨立寫入時,Android刷新到磁盤(這是非常緩慢的)。如果你在一堆中做了這些改變,所有改變都是在1次寫入中完成的。

至於保持1個幫助程序實例,這裏是我的一個最近的一篇博客看:

http://touchlabblog.tumblr.com/post/24474750219/single-sqlite-connection

我寫了一些相當複雜的引用計數的邏輯,我早落實OrmLite的Android端口的一部分,但在這一點上我不認爲這是完全必要的。

http://touchlabblog.tumblr.com/post/24474455802/ormlite-for-android

對於鏈路完整性,我的博客帖子大約sqlite的鎖定和多個連接:

http://touchlabblog.tumblr.com/post/24474398246/android-sqlite-locking

+0

現在這些鏈接已經死了,你可以發佈當前的鏈接,我真的很有興趣閱讀這些鏈接。謝謝! – Matthias

+1

你是對的。將需要挖掘,看看我是否有他們。如果他們存在,他們將在http://touchlabblog.tumblr.com –

+0

發現他們,謝謝! – Matthias