SQLite 备份不能只复制 db 文件:做一次能恢复的演练
SQLite 很适合小型站点,但备份时不能只想着“把 .db 拷走”。如果数据库开了 WAL,现场可能还有 -wal 和 -shm 文件;如果站点有上传目录,文章附件和头像也要一起保存;如果恢复顺序没写,真出事时很容易漏步骤。
下面按一个 Node/Express 小站点举例,路径可以按你的项目改。
先确认要备份什么
常见运行期文件:
data/blog.db
uploads/
.env
如果 SQLite 开了 WAL,运行中还可能看到:
data/blog.db-wal
data/blog.db-shm
不要手动拼这些文件。优先用 SQLite 自己的 .backup,它会拿到一致的数据库快照。
1. 建备份目录
mkdir -p data/backups
给备份文件带时间戳:
stamp=$(date +%Y%m%d-%H%M%S)
echo "$stamp"
macOS/Linux 可以直接用。Windows PowerShell 等价写法:
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$stamp
2. 备份数据库
Linux/macOS:
sqlite3 data/blog.db ".backup 'data/backups/blog-$stamp.sqlite'"
PowerShell:
sqlite3 data/blog.db ".backup 'data/backups/blog-$stamp.sqlite'"
验证备份文件:
sqlite3 data/backups/blog-$stamp.sqlite 'pragma integrity_check;'
sqlite3 data/backups/blog-$stamp.sqlite '.tables'
正常应该输出:
ok
只看到文件存在不算验收。至少要跑一次 integrity_check。
3. 备份上传目录
Linux/macOS:
tar -czf data/backups/uploads-$stamp.tar.gz uploads
PowerShell 如果有 tar:
tar -czf data/backups/uploads-$stamp.tar.gz uploads
验证压缩包能列出内容:
tar -tzf data/backups/uploads-$stamp.tar.gz | head
如果项目暂时没有 uploads/,也要在备份说明里写清楚“没有上传目录”,不要让下一个维护者猜。
4. 记录环境变量模板,不要乱传密钥
.env 里经常有密钥,不能随便上传到 Git 或聊天工具。
保存两份东西:
.env.example:不含真实密钥,记录需要哪些变量。- 真实
.env:只进受控备份,不进 Git。
检查 Git 是否会误收:
git check-ignore -v .env || echo '.env is not ignored'
如果输出 .env is not ignored,修 .gitignore。不要等提交前再靠肉眼检查。
5. 写一份恢复顺序
放到 data/backups/RESTORE.md 或运维文档里都可以。内容不要写成概念,要写命令。
示例:
# 恢复顺序
1. 停止服务:`pm2 stop codenest`
2. 备份现有现场:`cp data/blog.db data/blog.db.before-restore`
3. 恢复数据库:`cp data/backups/blog-YYYYMMDD-HHMMSS.sqlite data/blog.db`
4. 恢复上传目录:`tar -xzf data/backups/uploads-YYYYMMDD-HHMMSS.tar.gz`
5. 检查数据库:`sqlite3 data/blog.db 'pragma integrity_check;'`
6. 启动服务:`pm2 start codenest`
7. 健康检查:`curl -fsS http://127.0.0.1:3000/health`
8. 查看日志:`tail -n 50 data/logs/error.log`
恢复文档的标准是:不熟悉项目的人照着做,也不会把顺序弄反。
6. 做一次临时目录恢复演练
不要第一次恢复就直接覆盖生产目录。先在临时目录演练。
mkdir -p /tmp/codenest-restore-test
cp data/backups/blog-$stamp.sqlite /tmp/codenest-restore-test/blog.db
tar -xzf data/backups/uploads-$stamp.tar.gz -C /tmp/codenest-restore-test
sqlite3 /tmp/codenest-restore-test/blog.db 'pragma integrity_check;'
find /tmp/codenest-restore-test -maxdepth 2 -type f | head
看两件事:
- 数据库能打开且校验通过。
- 上传文件确实解出来了。
7. 恢复到原项目时的安全顺序
先停服务:
pm2 stop codenest
如果不是 PM2,换成你的进程管理方式。关键是恢复数据库时不要还有写入。
保留现有现场:
cp data/blog.db data/blog.db.before-restore-$stamp
恢复数据库:
cp data/backups/blog-$stamp.sqlite data/blog.db
恢复上传目录前先挪走旧目录,不要直接混合覆盖:
mv uploads uploads.before-restore-$stamp
mkdir uploads
tar -xzf data/backups/uploads-$stamp.tar.gz
启动并验证:
pm2 start codenest
curl -fsS http://127.0.0.1:3000/health
tail -n 50 data/logs/app.log
tail -n 50 data/logs/error.log
如果健康检查失败,先看 error.log,不要连续重启赌运气。
8. 容易漏的东西
定时任务状态
如果项目有定时发布、队列、后台任务,数据库恢复到旧时间点后,任务可能会重复执行或漏执行。恢复文档里要写清楚恢复后检查哪张表、哪个后台页面或哪个日志事件。
外部回调
支付、OAuth、Webhook 这类外部系统通常不会因为你恢复数据库就自动回到旧状态。恢复后要检查回调积压和失败重试。
文件权限
恢复后的文件属主不对,服务也会启动失败:
ls -la data uploads
如果线上服务用单独用户运行,恢复后要确认服务用户能读写运行期目录。
9. 每周备份的最低验收
stamp=$(date +%Y%m%d-%H%M%S)
sqlite3 data/blog.db ".backup 'data/backups/blog-$stamp.sqlite'"
sqlite3 data/backups/blog-$stamp.sqlite 'pragma integrity_check;'
tar -czf data/backups/uploads-$stamp.tar.gz uploads
tar -tzf data/backups/uploads-$stamp.tar.gz >/dev/null
ls -lh data/backups/blog-$stamp.sqlite data/backups/uploads-$stamp.tar.gz
这些命令都过了,才算“这次备份能用”。
还没有评论,欢迎先发第一条。