Android 将数据库日志模式从删除迁移到WAL
我在我的应用程序中提供了一些导出/导入功能,现在我看到,如果旧的导出被导入到新的android版本中,这会产生问题,因为在许多运行android 9或更高版本的手机上,Android 将数据库日志模式从删除迁移到WAL,android,sqlite,android-sqlite,Android,Sqlite,Android Sqlite,我在我的应用程序中提供了一些导出/导入功能,现在我看到,如果旧的导出被导入到新的android版本中,这会产生问题,因为在许多运行android 9或更高版本的手机上,SQLite数据库确实使用了journal\u模式WAL,而不是在老式手机上使用的DELETE 信息/观察: 我没有在我的应用程序中设置手动日志模式(例如在SQLiteOpenHelper中) 并非所有android 9手机都启用了此功能(我的S9运行饼图仍然使用DELETE模式),因此在我的手机上恢复旧的备份效果非常好 在未使
SQLite
数据库确实使用了journal\u模式
WAL
,而不是在老式手机上使用的DELETE
信息/观察:
- 我没有在我的应用程序中设置手动日志模式(例如在
中)SQLiteOpenHelper
- 并非所有android 9手机都启用了此功能(我的S9运行饼图仍然使用
模式),因此在我的手机上恢复旧的备份效果非常好DELETE
- 在未使用
模式的手机上,还原的备份会使我的应用程序崩溃,因为数据库对我的应用程序来说似乎是空的,我对此并不在意。当然,关注空数据库并不能解决问题,因为我需要导入的数据DELETE
- 如何确定当前手机默认使用的是
还是WAL
DELETE
- 如何找到给定
文件的模式*.db
- 如何为给定的
文件更改此模式*.db
WAL
,我更喜欢一些基于迁移的解决方案
如何确定当前手机默认使用WAL还是DELETE
如果设备使用Android 9+,那么如果正确实现,它应该默认为WAL模式。但是,设备提供商可以提供自定义/遗留实现。因此,您需要按照如下所示/回答进行检查(实际上使用下面的方法不需要检查)
崩溃的原因可能是您没有备份wal模式激活时存在的其他-wal和-shm文件
在实际进行备份之前,我使用下面的代码
- 显然DBConstants.DBNAME是数据库名
- 数据库存储在默认位置(data/data/the_package/databases/)
csr=db.rawQuery(“PRAGMA journal_mode”,null)
是查询日志模式的行,还有返回true或false的SQLiteDatabase方法
关于:-
如何为给定的*.db文件更改此模式
如果使用Android SDK,则可以使用SQLiteDatabase方法,也可以通过设置,但请注意何时可以执行此操作的限制 如果我决定在所有android版本中禁用WAL模式,我所要做的就是:1)在我的下一个应用程序版本中,我确保我的数据库尚未打开,因此没有代码访问数据库2)我执行你上面发布的更长的代码块,这确保所有更改都写入数据库文件3)我使用
SQLiteOpenHelper
像往常一样打开数据库,并在配置数据库时在其中调用disablewriteaheadloging
。这应该为所有设备保存,并且应该确保所有设备都在使用旧的日志模式,对吗?@prom85,是的,听起来正确。注意,上面的代码假设dbHelper连接已经关闭(关闭应该提交/检查点)。在应用程序重新启动后,它肯定会关闭,所以非常感谢你的帮助
private void checkpointIfWALEnabled(Context context) {
final String TAG = "WALCHKPNT";
Cursor csr;
int wal_busy = -99, wal_log = -99, wal_checkpointed = -99;
SQLiteDatabase db = SQLiteDatabase.openDatabase(context.getDatabasePath(DBConstants.DATABASE_NAME).getPath(),null,SQLiteDatabase.OPEN_READWRITE);
csr = db.rawQuery("PRAGMA journal_mode",null);
if (csr.moveToFirst()) {
String mode = csr.getString(0);
//Log.d(TAG, "Mode is " + mode);
if (mode.toLowerCase().equals("wal")) {
csr = db.rawQuery("PRAGMA wal_checkpoint",null);
if (csr.moveToFirst()) {
wal_busy = csr.getInt(0);
wal_log = csr.getInt(1);
wal_checkpointed = csr.getInt(2);
}
//Log.d(TAG,"Checkpoint pre checkpointing Busy = " + String.valueOf(wal_busy) + " LOG = " + String.valueOf(wal_log) + " CHECKPOINTED = " + String.valueOf(wal_checkpointed) );
csr = db.rawQuery("PRAGMA wal_checkpoint(TRUNCATE)",null);
csr.getCount();
csr = db.rawQuery("PRAGMA wal_checkpoint",null);
if (csr.moveToFirst()) {
wal_busy = csr.getInt(0);
wal_log = csr.getInt(1);
wal_checkpointed = csr.getInt(2);
}
//Log.d(TAG,"Checkpoint post checkpointing Busy = " + String.valueOf(wal_busy) + " LOG = " + String.valueOf(wal_log) + " CHECKPOINTED = " + String.valueOf(wal_checkpointed) );
}
}
csr.close();
db.close();
}