【PostgreSQL里insert on conflict do操作时的冲突报错分析】

最近在巡检PostgreSQL的数据库的时候,发现部分数据库里存在大量的如下报错

ERROR:  ON CONFLICT DO UPDATE command cannot affect row a second time
HINT:  Ensure that no rows proposed for insertion within the same command have duplicate constrained values.

image.png

一、问题分析

通过报错的字段可以看出是使用了PostgreSQL 9.5 引入的一项新功能,insert on conflict do功能,即UPSERT的效果,当插入遇到约束错误时,直接返回,或者改为执行UPDATE。观察日志可以看出执行的SQL是带有多条记录的,推测多条记录的key值冲突了,因此报了这个错。

PostgreSQL 的 upsert 功能:当记录不存在时,执行插入;否则,进行更新。

PostgreSQL的代码里src/backend/executor/nodeModifyTable.c下的ExecOnConflictUpdate()函数里的注释部分其实解释的很清楚了。当在同一命令中再次更新刚插入的元组时,可能会发生这种情况。例如,因为插入了多个具有相同冲突键值的行。

MERGE 也有同样的问题,SQL-2003标准也类似地规定MERGE,在尝试更新同一行两次时必须引发异常。因为一次请求中对行的处理,顺序是不固定的,数据库不知道应该以哪条为最后需要保留的数据。

注释部分也明确表示出现这种问题属于用户的责任,PostgreSQL不会主动去处理这种报错,这种不在同一条SQL中出现多条相同KEY的数据的问题应该让用户去保障。

image.png

二、问题复现

1.建立测试表


postgres<16.1>(ConnAs[postgres]:PID[1103345] 2024-04-16/14:09:21)=# create table test(id int primary key, info text, crt_time timestamp);
CREATE TABLE
postgres<16.1>(ConnAs[postgres]:PID[1103345] 2024-04-16/14:09:22)=#  insert into test values (1,'test',now()) on conflict (id) do update set info=excluded.info,crt_time=excluded.crt_time;
INSERT 0 1
postgres<16.1>(ConnAs[postgres]:PID[1103345] 2024-04-16/14:09:44)=# select * from test;
+----+------+----------------------------+
| id | info |          crt_time          |
+----+------+----------------------------+
|  1 | test | 2024-04-16 14:09:44.405528 |
+----+------+----------------------------+
(1 row)postgres<16.1>(ConnAs[postgres]:PID[1103345] 2024-04-16/14:09:51)=#  insert into test values (2,'hah','2024-04-16 14:01:33.640731') on conflict (id) do update set info=excluded.info,crt_time=excluded.crt_time;
INSERT 0 1
postgres<16.1>(ConnAs[postgres]:PID[1103345] 2024-04-16/14:10:01)=# select * from test;
+----+------+----------------------------+
| id | info |          crt_time          |
+----+------+----------------------------+
|  1 | test | 2024-04-16 14:09:44.405528 |
|  2 | hah  | 2024-04-16 14:01:33.640731 |
+----+------+----------------------------+
(2 rows)

image.png

2.模拟连续两次插入同样的主键值

可以看到,id是主键,我连续两次插入id=7,但是没有主键冲突,原本的insert变成了更新,把id=7的其他字段进行了更新。

postgres<16.1>(ConnAs[postgres]:PID[1103345] 2024-04-16/14:11:22)=#  insert into test values (7,'test',now()) on conflict (id) do update set info=excluded.
info,crt_time=excluded.crt_time;
INSERT 0 1
postgres<16.1>(ConnAs[postgres]:PID[1103345] 2024-04-16/14:11:38)=# select * from test where id=7;
+----+------+----------------------------+
| id | info |          crt_time          |
+----+------+----------------------------+
|  7 | test | 2024-04-16 14:11:38.229476 |
+----+------+----------------------------+
(1 row)postgres<16.1>(ConnAs[postgres]:PID[1103345] 2024-04-16/14:11:51)=#  insert into test values (7,'ha','2024-04-16 14:15:38.229476') on conflict (id) do upda
te set info=excluded.info,crt_time=excluded.crt_time;
INSERT 0 1
postgres<16.1>(ConnAs[postgres]:PID[1103345] 2024-04-16/14:12:11)=# select * from test where id=7;
+----+------+----------------------------+
| id | info |          crt_time          |
+----+------+----------------------------+
|  7 | ha   | 2024-04-16 14:15:38.229476 |
+----+------+----------------------------+
(1 row)	

image.png

3.模拟一条SQL包含相同的key值

可以看到,一个SQL里插入多个行记录,并且key值相同(违反主键冲突)的时候,报了ERROR: ON CONFLICT DO UPDATE command cannot affect row a second time。上文我们也通过代码的注释部分,知道了这种问题属于用户的责任,需要用户保障,因此这部分的内容可能需要结合业务侧进行分析,检查下业务逻辑了。

postgres<16.1>(ConnAs[postgres]:PID[1103345] 2024-04-16/14:10:03)=# insert into test values (3,'hah','2024-04-16 14:01:33.640731'),(3,'hah','2024-04-16 14:01:33.640731') on conflict (id) do update set info=excluded.info,crt_time=excluded.crt_time;
ERROR:  ON CONFLICT DO UPDATE command cannot affect row a second time
HINT:  Ensure that no rows proposed for insertion within the same command have duplicate constrained values.postgres<16.1>(ConnAs[postgres]:PID[1103345] 2024-04-16/14:10:27)=# insert into test values (4,'hah','2024-04-16 14:01:33.640731'),(5,'hah','2024-04-16 14:
01:33.640731') on conflict (id) do update set info=excluded.info,crt_time=excluded.crt_time;
INSERT 0 2
postgres<16.1>(ConnAs[postgres]:PID[1103345] 2024-04-16/14:10:38)=# select * from test;
+----+------+----------------------------+
| id | info |          crt_time          |
+----+------+----------------------------+
|  1 | test | 2024-04-16 14:09:44.405528 |
|  2 | hah  | 2024-04-16 14:01:33.640731 |
|  4 | hah  | 2024-04-16 14:01:33.640731 |
|  5 | hah  | 2024-04-16 14:01:33.640731 |
+----+------+----------------------------+
(4 rows)

image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/821045.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Winform重难点笔记

FrmMain.cs 中的 partial&#xff08;部分的&#xff09; 和 FrmMain.Designer.cs 中的 partial 一样&#xff0c;不是一个类的修饰符&#xff0c;是限定这个类本身的组成部分&#xff0c;叫做部分类。当程序在编译和运行时&#xff0c;会把 FrmMain.cs 中的 FrmMain 类 和 Frm…

前端console用法分享

console对于前端人员来讲肯定都不陌生&#xff0c;相信大部分开发者都会使用console来进行调试&#xff0c;但它能做的绝不仅限于调试。 最常见的控制台方法 作为开发者&#xff0c;最常用的 console 方法如下&#xff1a; 控制台打印结果&#xff1a; 今天我分享的是一些 co…

RabbitMQ Stream插件使用详解

2.4版为RabbitMQ流插件引入了对RabbitMQStream插件Java客户端的初始支持。 RabbitStreamTemplateStreamListener容器 将spring rabbit流依赖项添加到项目中&#xff1a; <dependency><groupId>org.springframework.amqp</groupId><artifactId>sprin…

java-spring 图灵 04

在Spring框架中&#xff0c;可以使用org.springframework.core.io.support.ResourcePatternResolver接口的resolveBasePackage方法来将指定的基础包解析为用于包搜索路径的模式规范。 例如&#xff0c;如果基础包是com.example.app&#xff0c;则可以使用resolveBasePackage方法…

微信小程序-绘制图片并分享下载(painter)

1、引入painter插件 painter官网地址 1.1 可通过官网的方法引入painter插件&#xff0c; 官方插件下载地址 1.2 可下载本文附带的插件包直接引入 1.2.1 复制下载下来的文件中的painter文件夹&#xff0c;将其放在components目录下 1.2.2 页面中引入并使用 .json {"…

Mac版2024 CleanMyMac X 4.15.2 核心功能详解 cleanmymac这个软件怎么样?cleanmymac到底好不好用?

近些年伴随着苹果生态的蓬勃发展&#xff0c;越来越多的用户开始尝试接触Mac电脑。然而很多人上手Mac后会发现&#xff0c;它的使用逻辑与Windows存在很多不同&#xff0c;而且随着使用时间的增加&#xff0c;一些奇奇怪怪的文件也会占据有限的磁盘空间&#xff0c;进而影响使用…

如何在 VM 虚拟机中安装 OpenEuler 操作系统保姆级教程(附链接)

一、VMware Workstation 虚拟机 若没有安装虚拟机的可以参考下篇文章进行安装&#xff1a; 博客链接https://eclecticism.blog.csdn.net/article/details/135713915 二、OpenEuler 镜像 点击链接前往官网 官网 选择第一个即可 三、安装 OpenEuler 打开虚拟机安装 Ctrl …

家居网购项目(手写分页)

文章目录 1.后台管理—分页显示1.程序框架图2.编写数据模型Page.java 3.编写dao层1.修改FurnDao增加方法 2.修改FurnDaoImpl增加方法 3.单元测试FurnDaoTest 4.编写service层1.修改FurnService增加方法 2.修改FurnServiceImpl增加方法3.单元测试FurnServiceTest 5.编写DataUtil…

计算机系列之操作系统的系统

2、大话操作系统的启动 当按下开机键时&#xff0c;BIOS 就会开始执行 ​ BIOS 就是放在主板上 ROM 里面的一段程序。 ​ ROM Read Only Memory&#xff08;只能读取的内存&#xff09; ​ 所以 BIOS 在出厂的时候就可以直接写死在 ROM 里面。 ​ 每次开机的时候&#xff…

windows下已经创建好了虚拟环境,但是切换不了的解决方法

用得多Ubuntu&#xff0c;今天用Windows重新更新anaconda出问题&#xff0c;重新安装之后&#xff0c;打开pycharm发现打开终端之后&#xff0c;刚开始是ps的状态&#xff0c;后面试了网上改cmd的方法&#xff0c;终端变成c盘开头了 切换到虚拟环境如下&#xff1a;目前的shell…

ROS 2边学边练(26)-- 监测参数变化(C++)

前言 通常&#xff0c;一个节点需要对其自身参数或另一个节点的参数的更改做出响应。ParameterEventHandler类使监听参数更改变得容易&#xff0c;这样代码就可以对它们做出响应。 动动手 创建一个包 进入工作空间根路径的src下&#xff08;ros2_ws/src&#xff09;&#xff…

【Python基础】—— scipy.spatial.KDTree、matplotlib.pyplot、imageio

scipy.spatial参考博客&#xff1a;Python点云处理——建立KDtree 1 KDtree算法原理 KDtree构建出了一种类似于二叉树的树形数据存储结构&#xff0c;每一层都对应原始数据中相应的维度&#xff0c;以K层为一个循环&#xff0c;因此被称为KDtree。 每一层的左右子树的划分依据…

视频自定义字幕,中英文,彩色的,你也可以,不会不知道吧

前言 关于【SSD系列】&#xff1a; 前端一些有意思的内容&#xff0c;旨在3-10分钟里&#xff0c;有所获&#xff0c;又不为所累。 字幕&#xff0c;大家见过吧&#xff0c;其实你也可以&#xff0c;真的可以&#xff0c;真的真的可以。不难&#xff0c;不难&#xff0c;真的…

如何评估一个RAG(检索增强生成)系统

本文首发自博客文章 如何评估一个RAG&#xff08;检索增强生成&#xff09;系统 RAG 概念最初来源于 2020 年 Facebook 的一篇论文&#xff0c;这是 Facebook 博客对论文内容的进一步解释 &#x1f449;《检索增强生成&#xff1a;简化智能自然语言处理模型的创建》。大家都知…

【C++对于C语言的扩充】函数重载、引用以及内联函数

文章目录 &#x1f680;前言&#x1f680;函数重载注意&#xff1a;✈️为什么C可以实现函数重载&#xff0c;而C语言却不行呢&#xff1f; &#x1f680;引用✈️引用的特性✈️C中为什么要引入引用✈️引用与指针的区别 &#x1f680;内联函数✈️内联函数特性 &#x1f680;…

GitHub提交PR

本教程只做开源代码库Github工程提交pr的教程&#xff0c;不做其他的深入的讲解 Github和Gitlab的操作类似&#xff0c;只不过Github叫PR&#xff0c;GitLab叫MR&#xff0c;基本上做法是一致的 以开源项目QuickChat为例 https://github.com/Binx98/QuickChat https://github…

C++项目 -- 负载均衡OJ(一)comm

C项目 – 负载均衡OJ&#xff08;一&#xff09;comm 文章目录 C项目 -- 负载均衡OJ&#xff08;一&#xff09;comm一、项目宏观结构1.项目功能2.项目结构 二、comm公共模块1.util.hpp2.log.hpp 一、项目宏观结构 1.项目功能 本项目的功能为一个在线的OJ&#xff0c;实现类似…

研发岗-统信UOS系统配置npm git等前端常用配置

第一步 获取root权限 配置环境等都需要用到root权限&#xff0c;所以我们先获取到root权限&#xff0c;方便下面的操作 下载软件 在UOS应用商店下载的所需应用 版本都比较低 安装node 官网下载了【arm64】的包&#xff0c;解压到指定文件夹&#xff0c;设置链接&#xff0…

苹果电脑启动磁盘是什么意思 苹果电脑磁盘清理软件 mac找不到启动磁盘 启动磁盘没有足够的空间来进行分区

当你一早打开苹果电脑&#xff0c;结果系统突然提示&#xff1a; “启动磁盘已满&#xff0c;需要删除部分文件”。你会怎么办&#xff1f;如果你认为单纯靠清理废纸篓或者删除大型文件就能释放你的启动磁盘上的空间&#xff0c;那就大错特错了。其实苹果启动磁盘的清理技巧有很…

STM32之HAL开发——CubeMX配置串行Flash文件系统

配置流程 在开始配置FATFS前&#xff0c;需要提前配置好RCC的时钟&#xff0c;以及时钟的频率&#xff0c;另外还要配置好Debug选项&#xff08;选择串行&#xff09; 选项介绍 文件系统适用于SD卡&#xff0c;Disk磁盘等&#xff0c;需要我们将对应的驱动打开才可以使用。 …