两条写入路径要用内容判重
更新于 2026-07-08
**当同一条数据有两条写入路径(本地直写 + 远端镜像回灌)时,只用 `id` 去重一定会重复 —— 因为两条路径会给出不同的 id。** 判重必须用「内容 + 会话 + 时间窗」这类与来源无关的特征。症状与根因
- 现象:手机自己发的一条测试消息,同步回来后又在列表里出现了一次。
- 链路:App 本地先写入一次(本地 + app-server 流式);随后 watcher 从
~/.codex 读到同一轮,用另一个 message id 当 session_delta 推回 App;本地 upsert 只按 id 去重,于是当成新消息再插一条。
- 根因:去重键
id 是「路径相关」的,而重复判定需要「内容相关」的键。
正确做法
- 远端导入时增加镜像重复判断:同一内容、同一会话、相近时间窗内视为同一条,不再插入。
- 不要为了省事关掉 watcher —— 电脑原生同步还要靠它。去重是写入层的职责,不是数据源的职责。
- 一般化:「同一实体的多个 id」是常态(本地 id / 服务端 id / 镜像 id / 原始链接)。判重时用最靠近内容的那套特征。
相关
- 对照两端要用同一条标识 —— 反面同族:那条讲「对照时要用两端都认的 key」,这条讲「去重时不能用来源相关的 key」
- INSERT OR IGNORE会让旧行不更新 —— 同为「写入策略选错」导致的数据异常
- 文件被回退先分清是工具还是并发会话 —— 同为「同一份数据被两处改写」