-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Java|Kotlin 损坏、备份、修复
数据库作为二进制文件,当内部有部分数据不一致或丢失时,可能会发生数据库损坏。数据不一致或丢失的原因较多,可能是代码问题、操作系统或文件系统故障、磁盘损坏等等。从根源上,数据库损坏是不可能完全避免的。
因此,WCDB 内建了修复工具,可以尽最大限度地将数据找回,减少数据丢失。
WCDB 提供了数据库损坏的监测机制,可以使用Database.setNotification(whenCorrupted:)
注册数据库损坏的回调。当回调被调用时,代表发生了数据库损坏,可以进行处理。
// Java
database.setNotificationWhenCorrupted(new Database.CorruptionNotification() {
@Override
public void onCorrupted(Database database) {
//WCDB 检测到损坏之后,checkIfIsAlreadyCorrupted会始终返回 YES
assert database.checkIfIsAlreadyCorrupted();
}
});
// Kotlin
database.setNotificationWhenCorrupted { database ->
//WCDB 检测到损坏之后,checkIfIsAlreadyCorrupted会始终返回 YES
assert(database.checkIfIsAlreadyCorrupted())
}
还可以调用
checkIfCorrupted
接口主动检测数据库是否已经损坏,不过这个方法会遍历数据库的所有内容,相当耗时,不建议调用。
在有备份的情况,修复工具的能力将大大提升。在数据库内的数据发生变化时,元数据备份有可能会过期。因此对于一些关键的保存易失性数据的数据库,建议使用enableAutoBackup(bool)
接口开启数据库自动备份功能,这样 WCDB 可以在有数据更新之后自动更新备份的内容,让备份不会过期。
备份会带来额外的 IO 消耗,但是基本不会对数据库的读写性能产生影响。备份的文件会保存在数据库所在的目录之下,文件名为数据库的文件名后面添加
-incremental.material
、-first.material
或-last.material
。
除了自动备份的接口,WCDB 也提供了手动备份的接口backup
,不过不推荐使用。
如果需要指定只备份部分表格的内容,还可以使用filterBackup(BackupFilter)
来配置。
检测到数据库损坏之后,则需要修复数据库。数据库修复通过 Database.retrieve(with:)
接口完成。它将尝试从已损坏的数据库中读出数据,并插入到新数据库中。
修复过程根据数据库的大小不同,需要一定的时间。建议在界面上提示等待,并在子线程进行修复。Database.retrieve(with:)
方法的回调会不断更新数据库的修复进度,可以用来做界面展示。
// Java
// view.startLoading()
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// score 是数据修复的百分比
double score = database.retrieve(new Database.ProgressMonitor() {
@Override
public boolean onProgressUpdate(double percentage, double increment) {
// view.updateProgress(percentage)
return true;//如果返回false则中止修复逻辑
}
});
System.out.print(score * 100 + "% percent of data is recovered");
// view.stopLoading()
}
});
thread.start();
// Kotlin
// view.startLoading()
val thread = Thread {
// score 是数据修复的百分比
val score = database.retrieve { percentage, increment ->
// view.updateProgress(percentage)
true //如果返回false则中止修复逻辑
}
print((score * 100).toString() + "% percent of data is recovered")
// view.stopLoading()
}
thread.start()
对于可再生的数据,如可从服务端重新拉取的数据,直接将数据库删掉重建是更好的恢复手段。
数据库损坏后,如果数据库修复也失败了,或者暂时不想修复,可以将损坏的数据库转存起来,然后创建一个新数据库给用户使用。
数据库转存可以调用deposit()
方法来实现。可以使用containDepositedFiles()
来判断是否有转存的数据库,使用removeDepositedFiles()
来删除转存的数据库。
数据库转存之后,新建的数据库会将损坏数据库中的表格原样创建一份,然后将这些表格的sequence
值(具体见:[SQLite Sequence Table][SQLite-Sequence-Table])也同步过来,这样在新数据库写入的数据库使用的rowid不会和损坏的数据库冲突。
当数据库修复成功之后,之前转存的损坏数据库的内容会全部合并到新数据库中,数据就恢复完整了,而且被恢复的转存数据库也会自动删除掉。
- 欢迎使用 WCDB
- 基础教程
- 进阶教程
- 欢迎使用 WCDB
- 基础教程
- 进阶教程
- 欢迎使用 WCDB
- 基础教程
- 进阶教程
- 欢迎使用 WCDB
- 基础教程
- 进阶教程