PostgreSQL写入时报duplicate key value violates unique constraint。它表示某个唯一约束阻止重复值进入表,常见SQLSTATE为23505。
先定位冲突的是哪条唯一规则。删除约束来让请求通过,可能把业务唯一性问题变成脏数据。

用错误码与约束名定位冲突
记录SQLSTATE 23505、报错中的约束名、冲突键及对应写入请求。查看表结构或\d 表名,确认约束覆盖单列、组合列还是表达式索引。应用应优先按SQLSTATE分类,而不是依赖错误信息文本。
区分重复请求与业务冲突
同一请求被重试、并发生成相同业务编号,或导入数据与现有行冲突,都可能触发23505。先查现有记录的归属及创建时间,再看重试链路和键生成逻辑。重复请求应做幂等处理,真正不同实体的键冲突则应拒绝或换键。
何时使用ON CONFLICT
PostgreSQL的INSERT ... ON CONFLICT DO NOTHING可以跳过冲突,DO UPDATE可按明确冲突目标更新。只有业务允许覆盖或合并时才使用,且要确认更新字段和返回值;盲目DO NOTHING可能让调用方误以为新记录已创建。
不要依赖先查后插消除并发
两个请求都先SELECT判断不存在,随后仍可能同时INSERT。数据库唯一约束是最后一道一致性边界,应用应正确处理23505或使用适合的原子写入语句。先查后插不能取代唯一约束。
验收包括幂等与并发场景
用重复提交和并发请求检查预期行为:相同业务请求返回同一结果,真正冲突得到清晰错误,表内没有不该出现的重复数据。监控23505出现频率,持续上升时追查调用链。
云服务器上的变更建议
需要在VPS上复现时,可以在隔离环境先验证配置。萤光云与LightNode可按实际地区与资源需求选择;操作前保留快照或备份。
FAQ
问:23505能否直接重试同一INSERT?答:原值不变时仍会冲突;应先判断业务键与已存在记录的关系,再决定更新、忽略或返回错误。
温馨提示
温馨提示:修改唯一约束前备份并评估依赖它的查询、外键和应用幂等逻辑。


