Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android database corrupt, but can open in SQLite Manager. Recoverable?

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? :'(

like image 507
pgsandstrom Avatar asked Feb 22 '11 09:02

pgsandstrom


People also ask

How do I fix a corrupted SQLite database?

Download and configure Kernel SQLite Database recovery on your system. Start the tool, and the home screen will appear on the screen. Click Open to select the corrupt . db file you want to repair, and click Recover.

How can I recover SQLite database in Android?

We can retrieve anything from database using an object of the Cursor class. We will call a method of this class called rawQuery and it will return a resultset with the cursor pointing to the table. We can move the cursor forward and retrieve the data. This method return the total number of columns of the table.

Can SQLite get corrupted?

An SQLite database is highly resistant to corruption. If an application crash, or an operating-system crash, or even a power failure occurs in the middle of a transaction, the partially written transaction should be automatically rolled back the next time the database file is accessed.

How can I tell if SQLite database is corrupted?

To verify that you're truly suffering from database corruption, enter the following command into the shell: sqlite> PRAGMA integrity_check; If the response is anything other than ok, the database is integrity checks have failed and needs to be repaired.


1 Answers

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:

sqlite in.db .dump | sqlite out.db

...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...

like image 59
David Given Avatar answered Oct 10 '22 18:10

David Given