幂等性保障核心是使重复操作不改变最终结果:插入用唯一索引+IGNORE/ON CONFLICT;更新需带前置状态条件;删除应静默成功;复杂操作须结合唯一标识、状态机与事务控制。

SQL重复执行导致数据异常,核心在于缺乏幂等性保障。关键不是阻止重复,而是让重复操作不改变最终结果。
插入场景:用唯一约束+忽略策略防重复
插入时最常见问题是主键或业务唯一键冲突。直接报错不可取,应主动控制行为。
- MySQL用 INSERT IGNORE 或 ON DUPLICATE KEY UPDATE,后者可做轻量更新(如更新时间戳)
- PostgreSQL用 INSERT ... ON CONFLICT DO NOTHING 或 DO UPDATE
- 务必在业务字段(如订单号、流水号)上建唯一索引,这是幂等的物理基础
更新场景:带条件更新,避免无脑覆盖
UPDATE不能只写 SET status = 'done',要加上业务状态前置判断。
- 例如:UPDATE order SET status = 'shipped' WHERE id = 123 AND status = 'paid'
- 返回影响行数,为0说明已被处理,可直接返回成功,不抛错
- 避免用“先查再更新”,防止并发查到旧状态后被其他事务改掉(查-改非原子)
删除场景:允许重复删,但不报错
删除本质是“确保目标不存在”,重复执行本就该静默成功。
- 用 DELETE WHERE ... 即可,无需提前SELECT校验
- 若需确认是否真删了数据,可查影响行数,但不影响业务逻辑走向
- 慎用TRUNCATE,它不支持WHERE,也不具备幂等语义
复杂操作:拆解+状态机+唯一标识
跨表、含计算、分步执行的逻辑,靠单条SQL难保证幂等,需设计状态与上下文。
- 每笔业务操作绑定全局唯一ID(如trace_id、biz_id),记录到日志表或状态表
- 执行前先查该ID是否已成功处理,有则跳过;无则插入标记+执行,两步建议用事务包住
- 状态字段按业务流转定义(如 pending → processing → success / failed),只允许向后推进
基本上就这些。幂等不是加锁,也不是靠应用层重试控制,而是把“重复”当作常态,让SQL和逻辑天然容错。










