2010-11-21 82 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