android - SQLiteOpenHelper.setWriteAheadLoggingEnabled 导致错误日志行

标签 android android-sqlite

当我打电话

setWriteAheadLoggingEnabled(true);

在我的SQLiteOpenHelper子类的构造函数中,第一次使用数据库,创建后,可以看到如下错误日志项:

02-07 18:16:05.131  10426-10426/com.test E/SQLiteLog﹕ (1) no such table: test

当应用程序被终止并随后启动时,我得到:

E/SQLiteLog﹕ (283) recovered 10 frames from WAL file /data/data/com.test/databases/test-wal

但是,应用程序运行良好,实际上没有抛出任何异常。

当我不启用 WAL 时,日志项不存在。

日志错误是否值得担心?

编辑:我的DbHelper的代码:

public class DbHelper extends SQLiteOpenHelper {

private static final int DB_VERSION = 1;

public DbHelper(Context context) {
    super(context, Db.NAME, null, DB_VERSION);

    // setWriteAheadLoggingEnabled(true);
}

@Override
public void onConfigure(SQLiteDatabase db) {
    super.onConfigure(db);

    db.setForeignKeyConstraintsEnabled(true);
    db.enableWriteAheadLogging();
}

@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL(Db.TestGroup._CREATE_TABLE);
    db.execSQL(Db.Test._CREATE_TABLE);
    db.execSQL(Db.Task._CREATE_TABLE);
    db.execSQL(Db.TaskFullTextSearch._CREATE_TABLE);

    db.execSQL(Db.TaskFullTextSearch.Triggers.AFTER_INSERT);
    db.execSQL(Db.TaskFullTextSearch.Triggers.BEFORE_UPDATE);
    db.execSQL(Db.TaskFullTextSearch.Triggers.AFTER_UPDATE);
    db.execSQL(Db.TaskFullTextSearch.Triggers.BEFORE_DELETE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    // nothing
}

public int getTestCount() {
    Cursor cursor = getReadableDatabase().rawQuery(SELECT_TEST_COUNT, null);
    cursor.moveToNext();
    int count = cursor.getInt(0);
    cursor.close();

    return count;
}
}

DB 类是一个“契约”类,定义了表类和列以及一组 SQL 语句。

数据库助手是在自定义应用程序子类中创建的单例:

public class TestApplication extends Application {

private static DbHelper DB_HELPER;

@Override
public void onCreate() {
    super.onCreate();

    DB_HELPER = new DbHelper(getApplicationContext());
}

public static DbHelper getDbHelper() {
    return DB_HELPER;
}
}

编辑 2:我刚刚检查了当真的​​没有 test 表时会发生什么 - 应用程序崩溃:

E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.test, PID: 30663
android.database.sqlite.SQLiteException: no such table: test (code 1): , while compiling: select count(*) from test

最佳答案

经过一些实验,似乎出于某种原因,SQLite 将缓存的表列表作为与打开的连接关联的元数据的一部分。创建新表只会更新用于执行此操作的连接上的缓存。如果连接用于对未包含在其缓存元数据中的表执行某些操作,则它会提示该表不存在,即使操作本身已成功执行(并且缓存随后已更新)。

如果未启用预写日志记录,SQLiteDatabase 使用的连接池目前只允许一个连接用于读取和写入操作,大概是为了避免在writer 对数据库有独占锁。如果启用了预写日志记录,那么除了主要的写入连接之外,它还允许至少一个单独的读取连接(读取连接的确切限制由系统属性定义)。

SQLiteOpenHelper 在打开用于数据库初始化和升级/降级的写连接之前打开一个读取连接以获取版本信息。。如果未启用预写日志记录,则它们都是相同的连接。但是,如果在 初始化之前启用了预写日志记录,则读取连接的缓存不会反射(reflect)在初始化期间执行的任何结构更改(SQLite 在执行第一个查询时会在日志中提示这一点)。这可以通过从初始化完成后调用的 onOpen() 方法启用预写日志记录来解决。

关于frame recovery的日志,是SQLite在关闭所有连接时检查点并删除WAL文件造成的。如果持有连接的进程在没有显式关闭它们的情况下终止,则在随后打开新连接时执行此清理,并且 SQLite 会提示它。如果您在应用程序移至后台时关闭 SQLiteDatabase,则应该可以解决此问题。另一方面,如果您在整个应用程序中与数据库进行交互,那么这可能会出现问题并且难以实现,我不建议这样做。

关于android - SQLiteOpenHelper.setWriteAheadLoggingEnabled 导致错误日志行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28385069/

相关文章:

android - Shortcut API Android 多个applicationId

android - 如何在 Room Dao 中创建 insertOrThrow 方法?

java - 将值保存到数据库

android - 如何修复在 android 内容提供者中找不到的内容提供者 url?

java - 谷歌地图 : Saving markers to text file/other?

android - LocationManager requestLocationUpdates 和 android 中的 timertask

android - 如何在 Eclipse ADT v22.3 中增加堆大小

java - 如何根据第一个微调器中所做的选择从数据库中过滤第二个微调器值?

android - 为我的应用程序指定最大 sqlite db 大小。如何处理数据库完全异常

Android 数据绑定(bind)错误。找不到访问器