android-SQLiteOpenHelper.setWriteAheadLoggingEnabled导致错误日志行
作者:互联网
当我打电话
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语句.
数据库帮助器是在自定义Application子类中创建的单例:
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:我刚刚检查了当实际上没有测试表时会发生什么-应用程序崩溃:
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所使用的连接池当前仅允许一个连接用于读取和写入操作,大概是为了避免在写入者对数据库进行独占锁定时执行读取操作所导致的错误.如果启用了预写日志记录,则除主写连接外,它还允许至少一个单独的读连接(读连接的确切限制由系统属性定义).
SQLiteOpenHelper打开一个用于获取版本信息的读取连接,然后再打开用于数据库初始化和升级/降级的写入连接.如果未启用预写日志记录,则它们都是同一连接.但是,如果在初始化之前启用了预写日志记录,则读取连接的缓存不会反映初始化期间执行的任何结构更改(并且SQLite在执行第一个查询时会在日志中抱怨该更改).可以通过启用onOpen()方法的预写日志来解决此问题,该方法在初始化完成后调用.
至于有关帧恢复的日志,这是由于所有连接均关闭时SQLite检查点并删除WAL文件所引起的.如果在没有显式关闭连接的情况下终止了持有连接的进程,则当随后打开新连接时,将执行此清除操作,而SQLite会抱怨该连接.如果您将应用程序移至后台时关闭SQLiteDatabase,则应解决此问题.另一方面,如果您要在整个应用程序中与数据库进行交互,那么这可能会成问题且难以实现,因此我不建议您这样做.
标签:android-sqlite,android 来源: https://codeday.me/bug/20191120/2046372.html