目标
用 cp 直接拷贝正在写入的 SQLite 文件,会把写到一半的页和一个可能与副本不匹配的 journal 一起拷走,恢复时直接报 database disk image is malformed。在线 backup API 会在反复的事务中按页拷贝,产出一致快照。本食谱在备份前后分别做结构校验与逻辑哈希对比,把“应该没问题”变成可出示的证据。
步骤要点
- 先对源库跑 PRAGMA integrity_check,健康应输出 ok;若有页链错误,先修源库再谈备份。
- 继续跑 foreign_key_check 与 quick_check,空输出代表外键一致,quick_check 以更低成本覆盖行级损坏。
- 用 sqlite3 的 .backup 命令(backup API 封装)在线备份,期间允许写入,副本应通过 integrity_check。
- 分别对源库与副本执行 .dump 并比对 SHA-256,哈希一致即所有表、行与 schema 对象逻辑相同。
- 现场复现反模式:写入进行中用 cp 拷贝再校验,直观展示为什么在线拷贝必须用 backup API 或先做 checkpoint。
排错提示
源库 integrity_check 报错就停止备份先做恢复,用 .recover 把可读行抽到新库再从逻辑 dump 重建,别把损坏拷得更快;两次 dump 哈希不一致多半是备份后仍有写入,让写入静止或在同一读事务里做两次 dump;备份报 database is locked 是长读阻塞了 backup,重试 .backup 或改在写入空闲的时段调度。
适用边界
integrity_check 只验结构不验业务正确性,需配合外键检查与应用级不变量;dump 哈希是时点性证明,持续写入下要么在同一事务内对比要么接受最终一致。
代码示例
# 1) structural health of the source
sqlite3 app.db "PRAGMA integrity_check;" # -> ok
sqlite3 app.db "PRAGMA foreign_key_check;" # -> (empty = consistent)
# 2) online backup, safe under writes
sqlite3 app.db ".backup backup.db"
# 3) logical equality, not just file equality
sqlite3 app.db ".dump" | sha256sum # a1b2...
sqlite3 backup.db ".dump" | sha256sum # a1b2... identical
# 4) the anti-pattern, for the record
# cp app.db copy.db # pages mid-write -> malformed copy