Android 数据库已损坏,但可以在 SQLite Manager 中打开。可恢复吗?
最近两周,在没有发布应用程序更新的情况下,我开始收到大量数据库损坏的报告。下面是堆栈跟踪。 Android无法打开数据库,我电脑上的sqlite-manager程序也无法打开。然而,Firefox 的 SQLite 管理器插件可以打开它。运行命令“compact database”后,数据库被修复,我可以在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") 从应用程序内部进行真空吸尘,则没有帮助。这是为什么呢? :'(
In the latest two weeks, without releasing an update to my app, I have started getting a bunch of reports with corrupted databases. Below is the stacktrace. Android cannot open the database, and neither could the sqlite-manager program on my computer. However, the SQLite manager-addon to firefox could open it. After running the command "compact database", the database was fixed and I could open it in android. Is there any way I could do something like this within my app? The big problem is that I cannot even attempt to open the database, because newer versions of Android will immediately delete and replace the database, as you can see in the stacktrace below. Can PRAGMA Statements somehow be executed without opening the database?
Regards,
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)
Edit: I manager to open the database like this:
db = SQLiteDatabase.openDatabase(database, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);
But when I run this:
String sqlQuery = "pragma integrity_check";
db.execSQL(sqlQuery);
I get this:
ERROR/AndroidRuntime(9144): Caused by: android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed: pragma integrity_check
Edit2: I have realized that vacuuming the database fixes the issue. But if I vacuum from inside my app, with exeSQL("vacuum"), it does not help. Why is this? :'(
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
恢复损坏数据库的规范好方法是将其转储为 SQL,然后将其读回新数据库。使用 sqlite 工具非常简单:
...但是,当然,您需要在代码中完成它,而且我真的不知道 .dump 是否可以从任何地方获得。
我建议您可能首先要了解一下它是如何被损坏的 --- SQLite 对我来说一直坚如磐石,尽管我只在内部存储上使用过它。您可以检查 FAT 文件系统是否已损坏吗?例如,我见过数码相机会以各种晦涩的方式彻底破坏卡上的文件系统......
The canonical Good Way to recover a corrupt database is to dump it out as SQL and then read it back in to a new database. It's dead easy with the sqlite tool:
...but, of course, you need to do it in code, and I really don't know if .dump is available from anywhere.
I'd suggest that you possibly want to look in to how it's getting corrupted in the first place --- SQLite has always been rock solid for me, although I've only ever used it on the internal storage. Can you check the FAT filesystem to see whether it's corrupt? I've seen, e.g., digital cameras which will thoroughly mangle filesystem on cards in various obscure ways...
Android 删除数据库确实是一个问题。
我刚刚意识到一个解决方案可能是使用 SQLJet 而不是默认的 Android SQLite 实现。
正如它的名字所暗示的那样,SQLJet 是一个开源 Java SQLite 客户端,它可以在 Android 上运行。
Android deleting the database is an issue indeed.
I just realized a solution could be to use SQLJet instead of the default Android SQLite implementation.
As its name does not suggest, SQLJet is an open source Java SQLite client, and it works on Android.
在您的应用程序中,您在退出活动之前是否关闭数据库?运行应用程序时观察 logcat 并检查是否有任何错误或警告。
In your app does you close the database before you exit the activity? Watch the logcat and check if there are any errors or warnings when you run your app.