Android 数据库损坏,但可以在 SQLite 管理器中打开。可恢复?

标签 android database sqlite corruption pragma

最近两周,我没有发布应用更新,却开始收到一堆数据库损坏的报告。下面是堆栈跟踪。 Android打不开数据库,我电脑上的sqlite-manager程序也打不开。但是,firefox 的 SQLite manager-addon 可以打开它。运行“压缩数据库”命令后,数据库已修复,我可以在 android 中打开它。有什么办法可以在我的应用程序中做这样的事情吗?最大的问题是我什至无法尝试打开数据库,因为较新版本的 Android 会立即删除并替换数据库,正如您在下面的堆栈跟踪中看到的那样。是否可以在不打开数据库的情况下以某种方式执行 PRAGMA 语句?

问候,

02-22 09:55:20.245: ERROR/Database(5382): CREATE TABLE android_metadata failed
02-22 09:55:20.245: ERROR/Database(5382): Failed to setLocale() when constructing, closing the database
02-22 09:55:20.245: ERROR/Database(5382): android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed
02-22 09:55:20.245: ERROR/Database(5382):     at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method)
02-22 09:55:20.245: ERROR/Database(5382):     at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:1950)
02-22 09:55:20.245: ERROR/Database(5382):     at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1818)
02-22 09:55:20.245: ERROR/Database(5382):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:817)
02-22 09:55:20.245: ERROR/Database(5382):     at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:851)
02-22 09:55:20.245: ERROR/Database(5382):     at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:844)
02-22 09:55:20.245: ERROR/Database(5382):     at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:540)
02-22 09:55:20.245: ERROR/Database(5382):     at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203)

02-22 09:55:20.245: ERROR/Database(5382): Deleting and re-creating corrupt database /mnt/sdcard/myapp/backup.sqlite
02-22 09:55:20.245: ERROR/Database(5382): android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed
02-22 09:55:20.245: ERROR/Database(5382):     at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method)
02-22 09:55:20.245: ERROR/Database(5382):     at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:1950)
02-22 09:55:20.245: ERROR/Database(5382):     at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1818)
02-22 09:55:20.245: ERROR/Database(5382):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:817)
02-22 09:55:20.245: ERROR/Database(5382):     at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:851)
02-22 09:55:20.245: ERROR/Database(5382):     at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:844)
02-22 09:55:20.245: ERROR/Database(5382):     at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:540)
02-22 09:55:20.245: ERROR/Database(5382):     at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203)

编辑:我经理像这样打开数据库:

db = SQLiteDatabase.openDatabase(database, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);

但是当我运行这个时:

String sqlQuery = "pragma integrity_check";
db.execSQL(sqlQuery);

我明白了:

ERROR/AndroidRuntime(9144): Caused by: android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed: pragma integrity_check

Edit2:我意识到清理数据库可以解决问题。但是,如果我使用 exeSQL("vacuum") 从我的应用程序内部吸尘,它无济于事。为什么是这样? :'(

最佳答案

恢复损坏数据库的典型好方法是将其转储为 SQL,然后将其读回新数据库。使用 sqlite 工具非常简单:

sqlite in.db .dump | sqlite out.db

...但是,当然,您需要在代码中执行此操作,而且我真的不知道 .dump 是否可以从任何地方获得。

我建议您可能首先想看看它是如何被破坏的——SQLite 对我来说一直是坚如磐石的,尽管我只在内部存储上使用过它。你能检查 FAT 文件系统看它是否损坏了吗?例如,我见过数码相机会以各种晦涩的方式彻底破坏卡上的文件系统...

关于Android 数据库损坏,但可以在 SQLite 管理器中打开。可恢复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5076119/

相关文章:

iphone - 打开并查看 .sqlite 文件的内容

python - Django 1.4 定义用户

Android 剪辑 canvas.drawBitmap

带有动画的 Android Fragment Transaction 导致白色闪光

java - 无法识别 Android ParseDateException EDT 时区

mysql - 将 CSV 导入 mysql 数据库,其中一个单元格包含多个用逗号分隔的值

django - 在 Django 中使用带有错误处理的原子 block

python - Pyinstaller 无法将信息插入到 sqlite 数据库文件 --onefile

java - 表 Ord 没有名为 _id 的列

Android 数据绑定(bind)点击监听器不工作(随机工作)