SQLite 在线备份别只复制 db 文件:建立可恢复的备份流程

10-01 4阅读

SQLite 把数据库放进文件,容易让人把“复制文件”误认为完整备份方案。真正要保证的是:备份能够表示一个一致的数据库状态,而且恢复时应用能读懂它。本文针对仍在被应用使用的普通 SQLite 数据库;示例会创建新备份文件,不会覆盖生产库。

SQLite 在线备份别只复制 db 文件:建立可恢复的备份流程

AI生成概念配图:通过数据库感知的复制流程生成可验证的备份,仅辅助理解,不代表真实界面或实测结果。

为什么直接复制可能不够

启用 WAL 后,已经提交的修改可能仍在 -wal 文件中,尚未回写主数据库。单独复制 .db,可能遗漏这些修改;随手分别复制 .db 和 -wal,也不能保证它们来自同一时刻。不要删除 WAL 文件来“清理现场”。是否能安全复制,需要数据库状态、连接与文件系统快照条件共同保证。

更适合作为日常入口的是 SQLite 在线备份接口。命令行工具的 .backup 能把数据库备份到另一个文件;应用也可以调用 Backup API。它们理解数据库的一致性,而不是盲目按文件字节复制。备份仍然需要时间、空间和错误处理,不能把“在线”理解为完全没有资源影响。

先建立明确的输出路径

下面是 POSIX shell 示例。请先创建只允许备份账户访问的备份目录,并确认源文件存在。日期命名避免每次覆盖同一份文件;测试中的路径不应直接改成生产库路径。源库只读打开可避免路径拼错时意外创建空库。

set -eu
umask 077
src=/srv/app/app.db
dst=/srv/backups/app-$(date -u +%Y%m%dT%H%M%SZ).db
test -f "$src"
test ! -e "$dst"
sqlite3 -readonly "$src" ".backup '$dst'"
sqlite3 -readonly "$dst" "PRAGMA integrity_check;"

示例路径不包含单引号等特殊字符;如果路径来自外部输入,应改用语言绑定和参数化接口,不要拼接命令。脚本中的 set -e 会处理命令退出失败,但 integrity_check 报告逻辑问题时,不能只看 shell 退出码。必须检查它是否只返回 ok;其他结果都应把备份标记为待调查。

完整性通过,还要做业务抽查

integrity_check 检查数据库结构一致性,并不证明业务数据完整。存在外键时可补充 foreign_key_check,再选择应用自己的关键证据:最后一条任务记录、最新订单时间、核心配置条目。不要把正在持续变化的源库行数与较早完成的备份行数机械比较,时间点不同可能本来就有差异。

建议把备份文件名、开始与结束时间、程序版本、检查结果和文件校验值一起记录。校验值主要帮助发现传输或存储变化,不能替代数据库检查。只有验证通过的副本才进入可恢复清单;失败产物应单独标记,避免恢复时误拿最新但不完整的一份。

在隔离环境里完成恢复演练

恢复演练应先复制备份到新的测试目录,使用对应版本的应用连接它,执行只读冒烟检查。测试应用不要沿用生产邮件、支付或消息队列配置,否则一次“验证恢复”可能触发真实外部操作。正式恢复还需要停写、处理现有连接和相关辅助文件,并按应用维护流程切换,不能直接覆盖正在使用的数据库。

我的实践建议是把备份完成条件定义成“副本通过检查且最近做过恢复演练”。同磁盘副本可以应对误操作,却挡不住整盘故障;保留周期与异地副本应根据可接受的数据损失窗口决定。加密与访问控制也要覆盖备份,因为其中仍保存着原始业务数据。

参考资料

文章版权声明:除非注明,否则均为云鹊BLOG原创文章,转载或复制请以超链接形式并注明出处。