GaussDB/PostgreSQL 序列主键冲突 Duplicate key value violates unique constraint 解决方法
数据迁移后使用序列插入数据时报错 Duplicate key value violates unique constraint,本质是序列当前值小于表中已有主键值,导致新生成的序列值与已有数据重复。
问题场景
先迁移表结构,过一段时间再迁移数据。迁移前序列定义的 start 值为当时的值,而应用在数据迁移完成前可能已经新增了数据,导致迁移后序列当前值落后于表中实际主键值,新增数据时触发主键冲突。
解决方法
将序列当前值设置为大于表中最大主键值即可:
-- 设置序列当前值
select setval('seq1', 100);其中 seq1 为序列名称,第二个参数取表中主键的最大值加一。
查看序列当前值:
select last_value from seq1;如果是分布式数据库(如 GaussDB),需要在所有节点执行:
execute direct on all $$select get_nodename(), * from seq_name$$;序列常用操作
-- 查看下一个值(会递增序列)
select nextval('seq1');
-- 查看当前会话最近一次 nextval 返回的值
select currval('seq1');
select lastval('seq1');
-- 创建递增序列,起始值101,步长10
create sequence seq1 start 101 increment 10;序列参数说明
| 参数 | 说明 |
|---|---|
| increment | 步长,正数递增,负数递减 |
| start | 起始值,缺省递增为 minvalue,递减为 maxvalue |
| cache | 内存中预存序列号个数,缺省1表示无缓存 |
使用示例
-- 创建表
create table test1(id int primary key, name varchar(20));
-- 创建序列
create sequence test_seq2;
-- 绑定序列到字段默认值
alter table test1 alter column id set default nextval('test_seq2'::regclass);
-- 插入数据
insert into test1(name) values ('joe'),('scott'),('ben');
-- 查看数据
select * from test1;
-- id | name
-- ----+-------
-- 1 | joe
-- 2 | scott
-- 3 | ben
-- 查看序列当前值
select currval('test_seq2');
-- currval
-- ---------
-- 3
-- 查看表中最大主键
select max(id) from test1;
-- max
-- -----
-- 3
-- 查看序列详情
select * from test_seq2;注意事项
- 数据迁移完成后,务必检查所有序列的当前值是否大于对应表的最大主键值
- 分布式数据库需要在所有数据节点同步更新序列值
- 建议迁移后执行
select setval('seq_name', (select max(id) from table_name) + 1);一次性修正
评论