SQLiteOpenHelper.setWriteAheadLoggingEnabled 导致错误日志行
SQLiteOpenHelper.setWriteAheadLoggingEnabled causes an error log line
当我打电话时
setWriteAheadLoggingEnabled(true);
在我的SQLiteOpenHelper子class的构造函数中,第一次使用数据库,创建后,可以看到如下错误日志项:
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 class 是一个 'contract' class 并定义了 table classes 和列以及一堆 SQL 语句.
数据库助手是在自定义应用程序子程序中创建的单例class:
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
table 时会发生什么 - 应用程序崩溃:
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 保留了一个 table 的缓存列表作为与打开的连接关联的元数据的一部分。创建一个新的 table 只会更新用于执行此操作的连接上的缓存。如果连接用于对未包含在其缓存元数据中的 table 执行某些操作,则它会抱怨 table 不存在,即使操作本身已成功执行(并且缓存随后更新)。
如果未启用预写日志记录,SQLiteDatabase
使用的连接池当前只允许一个连接用于读取和写入操作,大概是为了避免写入器执行的读取操作引起的错误对数据库有独占锁。如果启用了预写日志记录,那么除了主要的写入连接之外,它还允许至少一个单独的读取连接(读取连接的确切限制由系统定义 属性)。
SQLiteOpenHelper
打开读取连接以获取版本信息 before 打开用于数据库初始化的写入连接和 upgrades/downgrades。如果未启用预写日志记录,则它们都是相同的连接。但是,如果在 before 初始化之前启用了预写日志记录,则读取连接的缓存不会反映在初始化期间执行的任何结构更改(并且 SQLite 在执行第一个查询时会在日志中抱怨这一点).这可以通过从初始化完成后调用的 onOpen()
方法启用预写日志记录来解决。
关于frame recovery的日志,是SQLite在关闭所有连接时检查点并删除WAL文件造成的。如果持有连接的进程在没有显式关闭它们的情况下终止,则在随后打开新连接时执行此清理,并且 SQLite 会抱怨它。如果您在应用程序移至后台时关闭 SQLiteDatabase
,则应该可以解决此问题。另一方面,如果您在整个应用程序中与数据库进行交互,那么这可能会出现问题并且难以实现,我不建议这样做。
当我打电话时
setWriteAheadLoggingEnabled(true);
在我的SQLiteOpenHelper子class的构造函数中,第一次使用数据库,创建后,可以看到如下错误日志项:
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 class 是一个 'contract' class 并定义了 table classes 和列以及一堆 SQL 语句.
数据库助手是在自定义应用程序子程序中创建的单例class:
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
table 时会发生什么 - 应用程序崩溃:
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 保留了一个 table 的缓存列表作为与打开的连接关联的元数据的一部分。创建一个新的 table 只会更新用于执行此操作的连接上的缓存。如果连接用于对未包含在其缓存元数据中的 table 执行某些操作,则它会抱怨 table 不存在,即使操作本身已成功执行(并且缓存随后更新)。
如果未启用预写日志记录,SQLiteDatabase
使用的连接池当前只允许一个连接用于读取和写入操作,大概是为了避免写入器执行的读取操作引起的错误对数据库有独占锁。如果启用了预写日志记录,那么除了主要的写入连接之外,它还允许至少一个单独的读取连接(读取连接的确切限制由系统定义 属性)。
SQLiteOpenHelper
打开读取连接以获取版本信息 before 打开用于数据库初始化的写入连接和 upgrades/downgrades。如果未启用预写日志记录,则它们都是相同的连接。但是,如果在 before 初始化之前启用了预写日志记录,则读取连接的缓存不会反映在初始化期间执行的任何结构更改(并且 SQLite 在执行第一个查询时会在日志中抱怨这一点).这可以通过从初始化完成后调用的 onOpen()
方法启用预写日志记录来解决。
关于frame recovery的日志,是SQLite在关闭所有连接时检查点并删除WAL文件造成的。如果持有连接的进程在没有显式关闭它们的情况下终止,则在随后打开新连接时执行此清理,并且 SQLite 会抱怨它。如果您在应用程序移至后台时关闭 SQLiteDatabase
,则应该可以解决此问题。另一方面,如果您在整个应用程序中与数据库进行交互,那么这可能会出现问题并且难以实现,我不建议这样做。