当前位置: 代码网 > it编程>数据库>MsSqlserver > UAT环境PostgreSQL ON CONFLICT DO UPDATE报错问题及解决

UAT环境PostgreSQL ON CONFLICT DO UPDATE报错问题及解决

2026年04月20日 MsSqlserver 我要评论
背景为应对最后上线测试,在 uat 环境进行一次总量3000万的数据集成,数据分为4种datasorce.在执行到第三种datasource时,集成失败。并收到告警邮件,提醒如下报错,讲这个报错前。就

背景

为应对最后上线测试,在 uat 环境进行一次总量3000万的数据集成,数据分为4种datasorce.

在执行到第三种datasource时,集成失败。并收到告警邮件,提醒如下报错,讲这个报错前。

就得下说一下当前数据集成方案:

### cause: psqlexception: error: on conflict do update command cannot affect row a second time
  建议:ensure that no rows proposed for insertion within the same command have duplicate constrained values.
; error: on conflict do update command cannot affect row a second time
  建议:ensure that no rows proposed for insertion within the same command have duplicate constrained values.; nested exception is org.postgresql.util.psqlexception: error: on conflict do update command cannot affect row a second time
  建议:ensure that no rows proposed for insertion within the same command have duplicate constrained values., 2025-06-18 14:31:12.729, 2025-06-18 15:50:03.329, 4213015, 20250618143057241, 1750227637384308, 2, 2025-06-18 17:10:06.947774, 2025-06-19 09:25:29.999212, 0, 2025-06-19 10:20:39.607914, 2025-06-19 10:36:15.499851
<==      total: 2
closing non transactional sqlsession [org.apache.ibatis.session.defaults.defaultsqlsession@4f49b57a]​

当前集成方案 (演示)

insert into master_order (order_id, order_info, product_info, geo_info)
select a.order_id,
  a.order_id,
  p.product_info,
  g.geo_info
from
  transaction_table
  a left join product_table p on a.product_no = p.product_no
  left join geo_table g on a.country_code = g.country_code
where
  version_number = '001' on conflict (order_id) do
    update
    set order_info = excluded.order_info,
    product_info = excluded.product_info,
    geo_info = geo_info.geo_info

这里使用的是 on conflict do update 函数. 又称 upsert 方式,即通过主键判断:当记录不存在 执行插入,否则进行更新!

建议:

  • 在做大数据量数据处理时.
  • 要优先使用upsert方式,避免使用先删除再插入方式。
  • 先删除在插入处理大数据量时性能不好,造成大量索引重建。
  • 数据页分 裂,大量空间碎片等问题。

upsert 使用限制

1.conflict(字段1,字段2) 必须为唯一主键

upsert 使用的字段必须要主键索引(pk)。必须主键pk. 二级索引都不行.

2.更新的数据源主键不允许重复

什么意思呢?

由于master_order 中 order_id 是唯一主键。

就必须要求数据源sql的结果中不允许有重复的 key(order_id).否则就报错. postgresql不会主动去处理这种报错, 需要用户自己来保障。

属于用户责任:

// 这个结果必须要唯一,一个order_id 只能有一条数据
select a.order_id,
  a.order_id,
  p.product_info,
  g.geo_info
from
  transaction_table
  a left join product_table p on a.product_no = p.product_no
  left join geo_table g on a.country_code = g.country_code
where
  version_number = '001'

问题分析

第一条!满足.

第二条!系统开发文档明明记录着 transaction_table 表 order_id 主键,product_table 表 product_no 是主键, geo_table 表 country_code 主键。所以应该也没问题啊!那为啥还报错?马上给pgsql 提 issue,发现bug 了......

最后检查发现,不知道哪位勇猛的好战友将 product_table 表中 product_no 主键去掉了。然后插入了两条一模一样的产品编号数据.在关联查询中就导致了一个 order_id 对应了多条订单数据。

解决:赶紧删除冗余数据.重新为product_table 表设置 product_no 主键索引.手动重启集成。危机解除!

。。可惜了,只是uat ,应该把生产环境都改咯才是好!

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com