Android SQLite 数据库损坏

标签 android sqlite

此链接准确描述了我的问题: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);
    }

}

最佳答案

很可能数据库进程在 I/O 期间被杀死。例如,通过任务 killer ,或者如果您允许数据​​库写入操作在应用程序应该关闭或休眠时继续进行......

看看您是否可以通过将您的应用程序置于数据库写入循环中并在其上使用任务 killer 来重现该问题。

场景:向数据库写入 32 个字节,编写器任务在仅写入 10 个字节后被终止,结果:数据库处于不一致且可能已损坏的状态。

另见: Android process killer

编辑:为每次读/写打开和关闭数据库?不要那么做! :)

关于Android SQLite 数据库损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2774726/

相关文章:

pandas - 如何使用 pandastable 更新数据库

android - 在 Activity 之间传递图像

java - Android Studio,是否有刷新按钮。每次我在 xml 中进行更改时,我都需要关闭并重新打开工作室以查看设计的更改

c++ - 如何在网络共享驱动器上使用 sqlite3 数据库?

ios - 将 NSMutableDictionary 插入 SQLite 数据库的 1 个单元格

performance - 为什么要从 Node.JS 的 sqlite block 中获取数据?

android - Facebook graph-api 安卓

android - Android 模拟器加载缓慢的原因是什么?

android - 谷歌眼镜 : imageView fullscreen?

android - 备份室数据库