2010-03-07 105 views
16

我正在開發一個Android應用程序。它有多個線程讀取和寫入Android SQLite數據庫。我收到以下錯誤:如何避免SQLiteException鎖定錯誤

SQLiteException: error code 5: database is locked

我明白了SQLite的鎖定在插入/更新整個數據庫,但這些錯誤似乎只是插入/更新,而我運行一個選擇查詢時發生。選擇查詢返回一個遊標,當我迭代它時,這個遊標被打開的時間相當長(幾秒鐘)。如果選擇查詢沒有運行,我永遠不會獲得鎖。我很驚訝,選擇可以鎖定分貝。這是可能的,還是其他的事情呢?

什麼是避免這種鎖的最好方法?

+0

你說離開光標開一會兒。我相信我有同樣的問題,但我的遊標正在由listView維護。你有沒有設法解決這個問題? – taer 2010-06-27 14:11:53

+1

是的,我通過將光標內容立即讀入集合中,關閉遊標然後遍歷集合來完成耗時的工作來解決這個問題。 如果您使用的是listView,您應該可以做同樣的事情並使用ArrayAdapter或編寫自己的適配器來擴展ArrayAdapter。 – TheArchedOne 2010-07-01 09:41:54

+0

http://stackoverflow.com/questions/7657223/sqlite-exception-database-is-locked-issue/9503044#9503044 – junto 2012-02-29 16:45:35

回答

2

通過避免將遊標留在「相當一段時間」打開。如果您可以負擔得起一次將所有數據存儲在內存中,那就這樣做。

如果不行,則嘗試增加忙閒超時。

1

遷移到ContentProvider而不是直接訪問數據庫。 ContentResolver爲您整理了所有線程問題,並允許其他有用的功能,例如在應用程序之間共享數據或與服務器同步。

ContentResolver的api開銷很小。您只需要定義一個AUTHORITY字符串(一個標識數據類型的唯一字符串 - 使用「com.example.myapp.contacts」類型的字符串)並使用ContentResolver.bla而不是db.bla。

7

您可能會在各個線程中打開和關閉多個數據庫連接。這是一個壞主意。只需打開一個數據庫連接,並在任何地方重複使用;然後SQLite將確保併發訪問序列化正確。

與jcwenger的回答一樣,使用ContentProvider是實現此目的的另一種方式,但需要對代碼進行更多幹擾性更改。

+0

我不打開和關閉數據庫多次,雖然我得到這個錯誤,請採取看[鏈接在這裏](http://stackoverflow.com/questions/13859840/application-crashes-on-installation-with-error-sqlite3-exec-failed-to-set-sync) – MobileEvangelist 2012-12-17 10:09:17

0

其造成的BeginTransaction你的代碼()function.Look,問題就解決了我的應用程序,以使註釋行此功能(調用BeginTransaction)線