数据库事务有个撤销键,按下去一切回到没发生之前;但智能体给客户发了通知、写了一条记录之后,撤销键常常失灵。这时就轮到补偿登场:不试图抹掉过去,而是再做一个动作把影响抵消掉。回滚和补偿的分界点,就在动作能不能撤销。
分界点:动作能不能撤销
判断标准只有一条:这个动作做完,系统还能不能干净地回到原点。改一条数据可以改回去,这是回滚的地盘;发出去的邮件、通知到人的消息,收不回来,只能靠补偿,比如再发一条更正说明。开工前把每一步按能不能撤销分好类,失败预案就完成了一半。分界点还会随外部条件移动:同一个动作,接了新的下游系统后可能从可撤销变成不可撤销,原来只写自家库,回滚容易;后来又同步给了合作方,撤回就管不到对面了。链路每次变更,都要重新过一遍可撤销性清单,这是最容易被跳过的一步。
两类动作的分野,可以压成这张对照:
| 维度 | 回滚 | 补偿 |
|---|---|---|
| 判定标准 | 动作做完,系统还能干净地回到原点 | 动作收不回来,只能再做一件事把影响拉平 |
| 典型场景 | 改一条数据再改回去 | 发出去的邮件再补一条更正说明 |
| 成立前提 | 所有改动都有明确的逆操作,且逆操作之间没有旁人插足 | 承认事情已经发生,不追求假装无事发生 |
| 最大的暗坑 | 多人同改时,可能把别人的改动一起冲掉 | 补偿本身也会失败,挂回原循环容易转出死循环 |
| 在链路里的位置 | 数据还没出系统时用 | 一旦发出去了就转补偿 |
回滚的适用条件和代价
回滚要求两点:一是所有已发生的改动都有明确的逆操作,二是逆操作之间没有旁人插足。多个人同时改同一份数据时,你的回滚可能把别人的改动一起冲掉,这是回滚最大的暗坑。所以回滚常配合版本快照用,回的是自己那一份的旧版本,互不牵连。演练也有讲究:只测成功路径的预案等于没预案,定期挑一两个真实失败场景走全流程,把发现的问题记回预案文档,预案才会越用越可靠。
补偿的本质是反向动作
补偿不追求假装无事发生,而是承认事情已发生,再做一件事把影响拉平。订错的单要冲正,发错的消息要澄清,转错的记录要更正。补偿动作自己也可能失败,所以要有重试和兜底,补偿链路比回滚更考验设计,值得单独排一遍演练。补偿还有一个别扭之处:它本身也可能出错,补偿失败后要不要再补偿?实务上给补偿动作设独立的重试和人工介入通道,别把它挂回原失败处理的循环里,那样容易转出死循环。
恢复动作靠什么做依据?靠事前留好的记录,执行日志和审计日志有什么区别? 讲了哪些记录是恢复的前提。批处理场景里恢复要分清楚是单条重来还是整批重来,见 批处理任务和交互任务有什么区别?。
真实系统里两者常搭配
一条链路里往往前半段能回滚、后半段只能补偿:数据还没出系统就回滚,一旦发出去了就转补偿。用智谱清言、通义千问这类模型自动生成内容再发布的流程就是典型,生成环节随便回退,发布环节出错就得靠撤回或更正来补偿。把分界点标在流程图上,团队就知道每个位置该挂哪种预案。给每个环节打上标记也有用:能回滚的标绿、只能补偿的标黄、两头都没有的标红,红色环节要么补设计要么改方案,带着红色上线是事故预定。
失败恢复速查表
- 可撤销、无旁人插足:回滚
- 已对外、收不回:补偿加更正
- 混合链路:标出回滚与补偿的分界点
预案写在出事之前,才来得及用上。
告警和复盘决定你多快发现需要恢复的那次失败,实时告警和事后复盘有什么区别? 讲了两层机制怎么配合;调外部服务出错时恢复策略更复杂,参考 内部工具和外部 API 差在哪?一文看懂。
回滚与补偿快问快答三则
- 能自动回滚就不需要补偿了吗?:链路里只要有一步对外发生,就离不开补偿,两者是并存的预案而非二选一。
- 补偿动作选什么时候触发?:确认原动作确实失败后尽快触发,拖着不补,影响面会越滚越大。
- 怎么测试恢复预案管不管用?:定期在测试环境真的失败一次,走完整恢复流程,纸面预案靠不住。


