PostgreSQL导入数据后序列id冲突的问题

- PostgresSQL导入大量数据

- PostgresSQL修改序列的id

1.导入大量数据的方法

PostgreSQL导入数据可以把数据按一条记录一行写入到一个文本文件,然后使用如下命令导入

\copy oplog from oplogfile.txt delimiter ',' ;

说明:delimiter ',' 代表每列以逗号分隔

【例】测试操作日志占用存储超过阈值触发清除的机制,需要插入大量数据

说明:这里的操作日志是记录软件图形化页面的操作,例如登录会记录一条日志;操作日志会存库

因为只是测试清除的功能,可以插入大量重复数据

(1)编辑 psqlinsert.sh,使用该脚本生成文本文件

#!/bin/bash
INSERT_NUM=1999594
START_ID=211
OUTPUT_FILE='/root/Downloads/oplogfile.txt'

rm -rf $OUTPUT_FILE
id=$START_ID
num=$INSERT_NUM

for((i=0;i<num;id++,i++))
  do echo "$id,admin,……,10.111.222.3"  >> $OUTPUT_FILE
done

说明:
- INSERT_NUM插入记录的行数,START_ID代表插入的第一条记录的id
- 第11按照表结构提供数据

(2)执行psqlinsert.sh后生成了文件oplogfile.txt

(3)将软件的其它服务停止,连接到PostgreSQL执行 \copy oplog from oplogfile.txt delimiter ',' ;

如果导入的数据量大需要等待一段时间

2.导入数据后出现的问题及解决

问题:

导入好数据确认已导入这些记录,将其它服务起来并登录页面,这时页面报SQL的错,类似如下,每次登录这个id会增加,但是后台查数据库并没有重复的记录

 把新导入的数据删除就可以登录,使用INSERT命令插入一条数据也会报错……

排查:

执行如下命令可以看到当前的最大id ->  1999805

select id from <table_name> order by id desc limit 1; 或者

select max(id) from <table_name>;

test=> select id from oplog order by id desc limit 1;
   id
---------
 1999805
(1 row)

test=> select max(id) from oplog;
   max
---------
 1999805
(1 row)

test=>

查看对应递增序列的下一个值 -> 216

select nextval('<sequence_name>');

test=> select nextval('oplog_id_seq');
 nextval
---------
     216
(1 row)

test=>

参考资料:

POSTGRESQL 插入数据时主键冲突异常 https://blog.csdn.net/ant98002/article/details/102248262/
PostgreSQL中序列相关函数 nextval、currval、lastval、setval、setval https://blog.csdn.net/carcarrot/article/details/106873197

test=> SELECT nextval('oplog_id_seq');
 nextval
---------
     393
(1 row)

test=> 
test=> SELECT currval('oplog_id_seq');
 currval
---------
     393
(1 row)

test=> SELECT nextval('oplog_id_seq');
 nextval
---------
     394
(1 row)

test=>

原因:

操作日志对应的表插入大量数据后最大的id到了1999805,但其对应的序列自增的id还停留在216,登录图形化界面的时候会记录一条日志,例如id为213,会与插入的数据冲突,所以页面报错

解决:

方法一,插入的数据从较大的id开始,避免与自增的冲突

方法二,修改序列对象计数器的值,至插入数据后的位置

select setval('<sequence_name>',<a num>);

test=> SELECT setval('oplog_id_seq',1999805);
 setval
---------
 1999805
(1 row)

test=>

3.导入大量数据测试清理表数据的整体步骤

生成包含大量记录的文本文件 -> 连接数据库导入文本文件中的数据 -> 更新对应序列计数器的值 

猜你喜欢

转载自blog.csdn.net/wy_hhxx/article/details/120953568