此链接完全描述了我的问题:http://old.nabble.com/Android-database-corruption-td28044218.html#a28044218
现在大约有300人使用我的Android应用程序,每次使用此堆栈跟踪向服务器发送崩溃报告:
android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2596) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621) at android.app.ActivityThread.access$2200(ActivityThread.java:126) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1932) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:123) at android.app.ActivityThread.main(ActivityThread.java:4595) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:521) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) at dalvik.system.NativeStart.main(Native Method) Caused by: android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed at android.database.sqlite.SQLiteQuery.native_fill_window(Native Method) at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:75) at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:295) at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:276) at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:171) at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:248)
结果是应用程序崩溃并且数据库中的所有数据都丢失了.
需要注意的一点是,每当我读取或写入数据库时,我都会得到一个新的SQLiteDatabase,并在完成后立即将其关闭.我这样做是为了防止这种腐败错误.
我还尝试使用单个静态对象同步所有数据库读取和写入,这似乎没有帮助.
这可能只是一个SQLite错误吗?
我在此处发现了与内置电子邮件应用程序类似的错误:http://code.google.com/p/android/issues/detail?id = 5610.
这是我的代码:
public class KeyValueTableAdapter extends BaseTableAdapter { private String tableName; private String keyColumnName; private String valueColumnName; public KeyValueTableAdapter(Context context, String tableName, String keyColumnName, String valueColumnName) { super(context); this.tableName = tableName; this.keyColumnName = keyColumnName; this.valueColumnName = valueColumnName; } protected String getStringValue(int key) { Cursor cursor = null; SQLiteDatabase db = null; String value; try { db = dbOpenHelper.getReadableDatabase(); cursor = db.query(true, tableName, new String[] { valueColumnName }, keyColumnName + "=" + key, null, null, null, null, null); if ((cursor.getCount() == 0) || !cursor.moveToFirst()) { value = null; } else { value = cursor.getString(0); } } finally { if (cursor != null) cursor.close(); if (db != null) db.close(); dbOpenHelper.close(); } return value; } } public abstract class BaseTableAdapter { protected DbOpenHelper dbOpenHelper; public BaseTableAdapter(Context context) { this.dbOpenHelper = new DbOpenHelper(context, DatabaseSettings.DATABASE_NAME, null, DatabaseSettings.DATABASE_VERSION); } }
Brad Hein.. 9
很可能数据库进程在I/O期间被杀死.例如,通过任务杀手,或者如果您允许数据库写入操作在应用程序关闭或休眠期间继续...
通过将您的应用程序置于数据库写入循环并在其上使用任务杀手来查看是否可以重现该问题.
场景:写入数据库的32个字节,写入任务在写入10后被杀死,结果:数据库处于不一致且可能损坏的状态.
另见: Android进程杀手
编辑:每次读/写打开和关闭数据库?不要那么做!:)
很可能数据库进程在I/O期间被杀死.例如,通过任务杀手,或者如果您允许数据库写入操作在应用程序关闭或休眠期间继续...
通过将您的应用程序置于数据库写入循环并在其上使用任务杀手来查看是否可以重现该问题.
场景:写入数据库的32个字节,写入任务在写入10后被杀死,结果:数据库处于不一致且可能损坏的状态.
另见: Android进程杀手
编辑:每次读/写打开和关闭数据库?不要那么做!:)