GORM 建表,指定主键 ID BIGSERIAL 及 duplicate key value violates unique constraint ``xxx_pk``
date
Aug 22, 2023
slug
duplicate key value violates unique constraint ``xxx_pke`` 问题解决过程
status
Published
tags
Go
Gorm
summary
GORM 踩坑日记
type
Post
Created Time
Oct 28, 2023 01:45 PM
Updated Time
Oct 28, 2023 01:45 PM
AI summary
在使用 GORM 建表时,如果出现
duplicate key value violates unique constraint
错误,可能是因为自增主键的值没有正确维护。在迁移数据时,如果 ID 值不为 0,就不会触发自增主键的更新,之后当 ID 为 0 时,就会从 1 或者随机的某个值开始进行自增,从而导致 ID 冲突。解决方法是在创建数据时忽略 ID 字段。Status
Done
今天,遇到了一个奇怪的问题,在新建一条数据时,报了如下错误:
我一看,这不是主键 ID 吗?怎么可能冲突呀!
首先,排查的方向是主键 ID 的数据类型,在 DDL 中看到,通过
CreateTable
方法创建出来的表DDL 如下:
我预期的主键 ID 是
BIGSERIAL
,现在创建出来的这个数据类型,其实也是 PostgreSQL 的自增,但会不会改成 BIGSERIAL
类型,问题就能够解决呢?这样创建出来的表,主键类型确实是
BIGSERIAL
了,但是问题还是没有解决。我仔细梳理了一下业务逻辑,在创建数据库表的时候,除了建表之外,还会从其他数据库表迁移一部分数据,迁移数据调用的方法是
BatchCreate
,此时,参数 list
中的数据 ID 是不为 0 的,这个过程不会失败,而之后,创建数据时,我并不会直接指定 ID,此时,就会报主键冲突的错误,而当我手动写入一条数据后,这个错误就会消失,问题会不会出现在这个 BatchCreate
上?经过尝试,当我将
BatchCreate
方法修改为如下结果时,主键冲突的问题就解决了。经过思考,我认为数据库表对每一个自增主键,都维护了一个自增值,首次迁移数据时,如果 ID 值不为 0,就不会触发这个自增主键的更新,因此,之后当 ID 为 0 时,这个自增主键就会从 1 或者随机的某个值开始进行自增,从而导致 ID 冲突。