天天看點

android.database.sqlite.SQLiteException: database is locked

在項目開發過程中,由于資料庫的架構設計問題,會很容易出現以下異常:

android.database.sqlite.SQLiteException: database is locked

注意:

   (1)這裡的異常資訊僅僅是android.database.sqlite.SQLiteException: database is locked, 在我研發過程中,還抛出了類似這樣的異常資訊。該異常是不可以被捕獲的。           (2)android.database.sqlite.SQLiteException: database is locked(一些資訊)。該異常是可以被捕獲的。

   這兩種異常顯然都是資料庫被鎖異常,但是異常資訊不同,說明引起異常的原因也不同。

   起初我認為這是由于在我操作資料庫的方法前面加了synchronized 的緣故,仔細想想,加這個是避免同時兩個線程去寫資料庫,在邏輯上是完全這确的。去掉之後多線程通路資料庫時,會出現資料庫關閉的異常,這是由于線程B通路完資料庫時,将資料庫關閉,線程A再通路資料庫引起,它們使用的是同一個資料庫對象。

    之後,我又查了很多資料,很多人提到了使用繼承ContentProvider的方式,來解決該異常。

    但是這種方式有2個弊端:

      1.使用繼承ContentProvider方式,會将項目的資料庫暴露給第三方。一般系統級應用,如存儲聯系人,         存儲短信的資料庫才有必要暴露給第三方。

      2.使用方式不如直接繼承SQLiteOpenHelper對象簡單。

Android技術文檔提到: A content provider is only required if you need to share data between multiple applications. For example, the contacts data is used by multiple applications and must be stored in a content provider. If you don't need to share data amongst multiple applications you can use a database directly via SQLiteDatabase. 

    如果需要在多個應用之間共享資料的話,ContentProvider方式才應該被使用。例如:聯系人資料被多個應用使用,那麼它就應該使用在ContentProvider方式存儲。如果你不需要共享資料,那麼僅僅使用SQLiteDatabase. 資料庫就可以了。

    現在不使用繼承ContentProvider的方式,我們該如何解決以上的異常呢?

    The reason a ContentProvider solves the problem is because it usually uses one single

SQLiteOpenHelper

 which means that there is only one connection to the database and the underlying

SQLiteDatabase

 takes care of the locking. You don't need a ContentProvider - just make sure you don't write to the DB using 2 different db connections. 

     A. ContentProvider能解決此問題的原因是它隻用一個單一的SQLiteOpenHelper對象,也就是說在app中僅僅有一個“資料庫連接配接” 連接配接着資料庫并且由SQLiteOpenHelper中的SQLiteDatabase負責維護資料庫的鎖。

    B. 你不需要一個ContentProvider - 隻要確定不要用2個不同的“資料庫連接配接”去連接配接資料庫就可以了。

以下是我的資料庫架構,希望能對大家有所幫助。

android.database.sqlite.SQLiteException: database is locked

你也可以參考 Android threading and database locking

轉至 :  http://blog.sina.com.cn/s/blog_74c22b2101010cwo.html