2010-11-21 70 views
5

突然之間,似乎我的應用程序正在使用的數據庫已經損壞。 我沒有更改數據庫的結構,但我今天在我的設備上多次重新部署應用程序。爲什麼我的Android SQLite數據庫突然變壞了?

它拋出以下異常。

E/Database(14281): CREATE TABLE android_metadata failed err=26 .. 
E/Database(14281): Failed to setLocale() when constructing, closing the database 
E/Database(14281): android.database.sqlite.SQLiteException: file is encrypted or is not a database 
E/Database(14281): at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method) 
E/Database(14281): at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:1848) 
E/Database(14281): at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1798) 
E/Database(14281): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:798) 
E/Database(14281): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:857) 
E/Database(14281): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:850) 
E/Database(14281): at android.app.ApplicationContext.openOrCreateDatabase(ApplicationContext.java:539) 
E/Database(14281): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:193) 
E/Database(14281): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:98) 
E/Database(14281): at com.ecs.android.gps.storage.DBAdapter.open(DBAdapter.java:75) 

數據庫使用SQLLiteOpenHelper類進行初始化。

public DBAdapter(Context ctx) 
{ 
    this.context = ctx; 
    DBHelper = new DatabaseHelper(context); 
} 

private static class DatabaseHelper extends SQLiteOpenHelper 
{ 
    DatabaseHelper(Context context) 
    { 
     super(context, DATABASE_NAME, null, DATABASE_VERSION); 
    } 

    @Override 
    public void onCreate(SQLiteDatabase db) 
    { 
     db.execSQL(DATABASE_CREATE); 
    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, 
    int newVersion) 
    { 
     Log.w(TAG, "Upgrading database from version " + oldVersion 
       + " to " 
       + newVersion + ", which will destroy all old data"); 
     db.execSQL("DROP TABLE IF EXISTS location_history"); 
     onCreate(db); 
    } 
} 
  • 我基本上打開/關閉兩個 每個 操作數據庫和遊標。
  • 一些文章指出 這是要走的路,但對於 Android應用程序,也不會更有意義 保持數據庫連接開放 所有的時間?
  • 我可以想象得到它 需要更多的資源 每次打開/關閉它。
  • 有多個活動和服務 訪問數據庫。 (可能在同一時間)
  • 我從來沒有看到在日誌

任何想法可能是什麼造成這一點,如何從中恢復,以及如何防止這種情況在未來的一個例外? 我有一個印象,由於一些併發問題(多個線程試圖打開/關閉或讀取/寫入數據庫),異常即將到來。我不知道SQLite數據庫在多線程訪問,鎖定等方面與普通數據庫(mysql-oracle)一樣健壯的程度。.....

+0

您是否看過使用數據提供程序跨多個實例共享數據? – Emile 2010-12-10 21:20:16

+0

這是在我的TO-DO清單上,並且據我所知,這可能是一個選項,因爲它爲你做了很多管道工作,但是,我只有一張表,我讀取和寫入。我也無意將數據公開給其他應用程序。我只想知道它是如何被破壞的,以及如何避免它(仍然使用std SQLiteDatabase和SQLiteOpenHelper類) – ddewaele 2010-12-10 22:46:46

+0

除非你已經修復它,否則我會進一步調查rosstheboss的答案。你提到你有訪問數據庫的服務和活動。鑑於兩個活動從來沒有真正活躍在同一時間,你可以假設有安全(r)。但是,您提到的服務可能會與活動同時運行。我不是java的專家,但我會想象有一些方法可以幫助鎖定/檢查數據庫上的鎖定。即已經打開,或鎖定/解鎖數據庫。這樣可以避免衝突,至少可以捕捉錯誤。 – Emile 2010-12-13 15:57:34

回答

0

可能使數據庫處於非法狀態不知何故,儘管通常會被標記出來,一切都進行得很好。

+0

我基本上打開/關閉每個操作的數據庫和遊標。有多個活動和服務可以訪問數據庫。但是,我從未在日誌中看到過例外情況。 – ddewaele 2010-11-27 23:53:58

+0

這裏最大的問題是沒有簡單的方法可以從中恢復。您基本上需要卸載應用程序(導致它刪除數據庫)並重新安裝以解除情況。 – ddewaele 2010-11-27 23:54:52

+0

你可以試試。轉到sdk工具文件夾,並運行我認爲的shell工具adb。然後使用sqlite3來瀏覽表格。如果這不起作用,您可能可以從這裏複製到本地機器,並使用其他工具進行恢復。 – Emile 2010-12-10 21:24:05

0

Ae sql lite數據庫文件不是文本可讀格式嗎?難道你不能解析數據庫文件來重建它嗎?此外,語言環境屬性,不是在Android爲您設置的元數據表上設置的。如果是這樣的話,那麼刪除該表並手動創建它可能會恢復您的數據庫。

+0

實現邏輯來重建數據庫文件是我真的不想在這裏實現的東西:) android_metadata確實是自動創建的,但是,從堆棧跟蹤來看,我的感覺是Android已經決定數據庫已經損壞,在這一點上,它刪除數據庫並重新創建它(我認爲這是標準的Android SQLite行爲)。在重新創建期間,它失敗了。我試圖弄清楚我做錯了什麼會導致腐敗。 – ddewaele 2010-12-10 22:43:38

+0

那麼你可以重複這個問題?每次你重新安裝了應用程序。 – Emile 2010-12-10 22:49:13

+0

註釋中提到的重新創建並不是指數據庫的初始創建(安裝應用程序時),而是指Android檢測到損壞的數據庫文件時發生的重新創建。這是很難重現...我可以讓應用程序運行幾天,突然它彈出。下次它可以在幾個小時後彈出。 – ddewaele 2010-12-10 23:04:16

相關問題