现象
相册照片从 130 张变成了 23 张。
起因:之前把 Netlify 每月 300 次的免费部署额度烧光了,网站停更了一段时间。这期间我在本地继续测试,上传了很多图片做验证。额度恢复、重新部署上线后,再拉代码本地预览时发现相册只剩 23 张,另外 107 张”消失”了。第一反应是数据丢了。
排查:三次误判
- 先查 git:照片文件和元数据都在
.gitignore里,根本不是提交问题。 - 以为本地环境没连上数据库:以为数据落到了本地磁盘 + JSON。其实本地
.env里 MongoDB 是配好的,一直连着线上库。 - 以为连错了库:数据一直好好躺在 MongoDB
lublog库的gallery_images集合里,130 条元数据一条没少——丢的不是元数据,是 107 张图片文件本身(本地测试时只存在本地磁盘,没传上去)。
根因:同步代码用”本地快照”覆盖了”线上数据”
相册有一个”同步”功能,把本地相册数据推送到线上数据库。这段同步代码的逻辑是:
1. 读取本地相册数据(把它当作最新、最全的)
2. 找出数据库里有、但本地数据里没有的记录 → 全部删除($nin)
3. 把本地数据整份写回数据库
这套逻辑成立的前提是本地数据是完整的。但当时我在本地测试,很多图片只存在本地、没传数据库,本地读到的是残缺的快照。同步一跑,数据库里那 107 条”本地没有的”真实记录,全被当成多余数据删掉了。
一句话:用残缺的本地快照,覆盖了完整的线上数据。
修复:从”全量对齐”改成”精确变更”
原代码是”先删后写”的全量对齐:
$nin:把数据库里”本地没有的”记录全删掉- 再整份写回
改成了只做精确变更:
- 要删除的记录:必须显式列出 id,用
$in精确删——只有明确要删的才删 - 其余记录:只做插入或字段更新,不做无差别的全量覆盖
这样即使本地数据残缺,同步也只把”本地新增的”写上去,永远不会因为”本地没有某条”就把线上数据删掉。
教训
- 全量删除类操作默认危险:
$nin、truncate、drop、“清空表再导入”这类代码,都要求”当前数据一定完整”才安全。看到就要警觉,先确认调用方的数据是不是可信的完整快照。 - “同步”类代码要防快照不完整:写同步逻辑时,默认假设”本地数据可能是残缺的”。数据边界——谁在写、从哪读、快照是否完整——必须自己 review,AI 不会替你想到”快照可能是残缺的”。
- 先确认数据在哪,再动手:库、集合、对象存储、本地文件,先搞清楚数据到底在哪,别按”我以为”推断,免得白折腾。
- 写库前先备份:任何覆盖写、批量删除前,先备份或保证可回滚,别让自己没有后悔药。
评论及留言规则
评论提交后需审核通过才会展示,请耐心等待。
请在交流中保持友善、理性和尊重。
你不得利用本站发布、传播或实施以下行为:
评论提交后需审核通过才会展示。什么是 Waline?