结论先说:如果重复触发只出现在个别样本,优先保留原始事件并追加修复标记;如果规模化后例外明显增多,则要冻结修复动作,先保留修复前快照再分批回放。两种做法的分界线不是重复次数,而是重复是否已经影响归因口径。下面给出可执行的记录结构,以及一个会让上述结论失效的反例。
转化事件被重复触发通常有三种来源,处理方式不同。第一种是同一用户行为被多次上报,比如页面刷新、返回后再次提交。第二种是同一转化被多个渠道各记一次,比如广告点击归因和站内事件同时成立。第三种是修复脚本本身重复执行,把历史数据又写了一遍。前两种要保留原始记录,第三种必须先停写再处理。
可区分的原因证据包括:事件时间戳是否集中在几秒内、同一用户标识是否出现多次、修复任务是否在重复区间内运行过。如果时间戳密集且用户标识相同,多半是上报层问题;如果时间跨度大且用户标识不同,更可能是归因口径问题。这两种判断会直接决定下一步是改采集还是改口径。
不要覆盖原记录。每次修复都写入一条新记录,并带上三个字段:修复批次、修复前值、修复后值。这样修复前后的差异可以单独查询,不必依赖备份还原。
event_id:原始事件标识,修复后仍指向同一条原始事件。fix_batch:本次修复批次,同一批处理共用同一值。value_before 与 value_after:修复前后的转化值或状态。fix_reason:重复触发、归因重叠或脚本重跑,三者要区分。实际动作是:先对重复区间做一次只读导出,把导出结果作为修复前快照存档,再执行修复。这个动作的结果会决定下一步——如果导出里已经存在同一事件的多次写入,说明问题在采集层,修复脚本只能止损,不能当成根因处理。
个别样本成立不代表可以照搬。假设某次修复只影响一个广告计划,重复事件集中在一次页面改版之后,那么按批次追加记录通常够用。但如果重复同时出现在多个计划、多个落地页,并且时间跨度和用户标识都不一致,就不能用同一批次统一处理。
这时应改为按来源分组:先按渠道或计划拆分,再对每组单独判断是采集重复还是归因重叠。分组之后,修复前快照也要按组保存,否则后续无法判断某一组的口径是否被改动过。这个边界是本文唯一需要强调的适用条件。
反例是:重复触发并非来自上报或归因,而是来自修复脚本反复读取同一份历史文件并重新写入。此时“保留原始事件并追加修复标记”会失效,因为每次追加都会产生新的重复记录,修复本身成了新的污染源。
判断方法是看修复批次之间是否出现相同的事件标识。如果同一标识在多个批次里反复出现,先停掉修复任务,保留最后一次修复前的完整快照,再单独确认脚本的读取范围。继续追加只会让修复前后记录混在一起,失去区分能力。
下一步不是继续修,而是先做一次对照:取修复前快照和修复后记录,按同一用户标识和时间窗口比对,确认差异只来自预期的那一类重复。如果差异超出预期,说明还有未识别的重复来源,应回到分组判断而不是扩大修复范围。
验收时以“能否单独还原修复前状态”为准,而不是以重复数量是否归零为准。重复数量下降也可能只是因为采集口径被改动,不能单独证明处理正确。只有当修复前快照可独立还原、修复后记录可逐条追溯时,这次处理才算留下了可用的前后记录。