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

 更新时间:2026年04月20日 09:35:19   作者:倒流时光三十年  
这篇文章主要介绍了UAT环境PostgreSQL ON CONFLICT DO UPDATE报错问题及解决过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

背景

为应对最后上线测试,在 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 ,应该把生产环境都改咯才是好!

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • postgresql中时间转换和加减操作

    postgresql中时间转换和加减操作

    这篇文章主要介绍了postgresql中时间转换和加减操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • postgresql查询自动将大写的名称转换为小写的案例

    postgresql查询自动将大写的名称转换为小写的案例

    这篇文章主要介绍了postgresql查询自动将大写的名称转换为小写的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • pgsql添加自增序列、设置表某个字段自增操作

    pgsql添加自增序列、设置表某个字段自增操作

    这篇文章主要介绍了pgsql添加自增序列、设置表某个字段自增操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • PostgreSQL中JSONB的使用与踩坑指南

    PostgreSQL中JSONB的使用与踩坑指南

    文章介绍了PostgreSQL中JSONB的使用,包括JSONB的基础操作、索引策略、数组操作和批量更新,文章通过实例详细讲解了JSONB的使用方法,帮助读者解决实际工作中的问题,感兴趣的朋友跟随小编一起看看吧
    2025-12-12
  • PostgreSQL基础备份与 WAL 日志备份完整代码实践

    PostgreSQL基础备份与 WAL 日志备份完整代码实践

    本文将深入探讨 PostgreSQL 的基础备份与 WAL 日志备份原理、配置方法、恢复策略,并结合 Java 应用场景,提供完整的代码示例与最佳实践建议,感兴趣的朋友跟随小编一起看看吧
    2026-03-03
  • PostgreSQL中常用的时间日期脚本使用教程

    PostgreSQL中常用的时间日期脚本使用教程

    PostgreSQL是一款简介而又性能强大的数据库应用程序,其在日期时间数据方面所支持的功能也都非常给力,下面就来看一下PostgreSQL中常用的日期时间脚本使用教程.
    2016-05-05
  • PostgreSQL 中唯一约束和唯一索引的区别小结

    PostgreSQL 中唯一约束和唯一索引的区别小结

    本文主要介绍了PostgreSQL 中唯一约束和唯一索引的区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-02-02
  • PostgresSQL安装教程及初始使用操作方法

    PostgresSQL安装教程及初始使用操作方法

    这篇文章介绍了如何在Linux系统上安装和配置PostgreSQL数据库,详细介绍了PostgreSQL的数据类型,并解释了如何使用序列来标识字段的自增长,感兴趣的朋友跟随小编一起看看吧
    2026-01-01
  • 在PostgreSQL中实现数据的自动清理和过期清理

    在PostgreSQL中实现数据的自动清理和过期清理

    在 PostgreSQL 中,可以通过多种方式实现数据的自动清理和过期处理,以确保数据库不会因为存储过多过时或不再需要的数据而导致性能下降和存储空间浪费,本文给大家介绍了一些常见的方法及详细示例,需要的朋友可以参考下
    2024-07-07
  • 在postgresql数据库中创建只读用户的操作

    在postgresql数据库中创建只读用户的操作

    这篇文章主要介绍了在postgresql数据库中创建只读用户的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12

最新评论