当前位置:   article > 正文

针对并发流程,出现数据插入重复的情况做以下优化 postgresql_pgsql插入大量数据的时候有重复值怎么办

pgsql插入大量数据的时候有重复值怎么办

背景介绍:

  业务场景:服务持续接收巡视任务的状态报文,解析报文后入库。业务处理逻辑:先根据报文中的唯一主键task_patrolled_id删除remove数据库中的表数据,然后再add插入新的数据。

  但是现在出现这种情况,两条报文上送上来的时间间隔为2毫秒,导致第一次上送报文的逻辑已经remove掉数据库中的数据,但是还未走到add入库,第一条数据还未入库。

此时第二条报文已经上报上来,在remove的时候,因第一条的add还未完成,导致remove失效,然后在第一条报文add的时候,第二条报文也add了,导致数据库出现两条task_patrolled_id相同的数据

 解决方法:

1.在表结构设计时,要把task_patrolled_id作为主键;

ALTER TABLE "public"."t_centralized_mission_state" ADD CONSTRAINT "test_pkey" PRIMARY KEY ("task_patrolled_id" );

这里设置主键时要注意,要先把原有的主键给删除掉,并且把表中,新主键重复的表数据给删除掉才行。

给一个删除表中重复数据的例子:

场景:表 t_centralized_mission_state 是一个任务进度表,每个任务进度都有一个新主键task_patrolled_id,还有update_time表示插入时间。因为有数据同时插入的情况,导致数据出现有重复task_patrolled_id的情况。id是根据 nextval 自动生成的,唯一。

删除重复task_patrolled_id的逻辑:

1.查出 task_patrolled_id 重复的数据,

  1. SELECT *
  2. FROM (
  3. SELECT DISTINCT (task_patrolled_id) ,count(*)
  4. FROM t_centralized_mission_state
  5. GROUP BY task_patrolled_id
  6. ) t
  7. WHERE count > 1

2.利用 row_number,获取到 t_centralized_mission_state 表中task_patrolled_id重复的、除了第一条以外的数据

  1. SELECT id
  2. FROM (
  3. SELECT id
  4. ,update_time
  5. ,task_patrolled_id
  6. ,row_number() OVER (PARTITION BY task_patrolled_id) AS row
  7. FROM (
  8. SELECT t1.update_time ,t1.id ,t2.*
  9. FROM t_centralized_mission_state t1
  10. ,(
  11. SELECT *
  12. FROM (
  13. SELECT DISTINCT (task_patrolled_id) ,count(*)
  14. FROM t_centralized_mission_state
  15. GROUP BY task_patrolled_id
  16. ) t
  17. WHERE count > 1
  18. ORDER BY count DESC
  19. ) t2
  20. WHERE t1.task_patrolled_id = t2.task_patrolled_id
  21. ORDER BY t2.task_patrolled_id
  22. ) t
  23. ) t1
  24. WHERE t1.row > 1

3.根据第二部筛选出来的id进行删除

  1. DELETE
  2. FROM t_centralized_mission_state
  3. WHERE id IN (
  4. SELECT id
  5. FROM (
  6. SELECT id
  7. ,update_time
  8. ,task_patrolled_id
  9. ,row_number() OVER (PARTITION BY task_patrolled_id) AS row
  10. FROM (
  11. SELECT t1.update_time
  12. ,t1.id
  13. ,t2.*
  14. FROM t_centralized_mission_state t1
  15. ,(
  16. SELECT *
  17. FROM (
  18. SELECT DISTINCT (task_patrolled_id)
  19. ,count(*)
  20. FROM t_centralized_mission_state
  21. GROUP BY task_patrolled_id
  22. ) t
  23. WHERE count > 1
  24. ORDER BY count DESC
  25. ) t2
  26. WHERE t1.task_patrolled_id = t2.task_patrolled_id
  27. ORDER BY t2.task_patrolled_id
  28. ) t
  29. ) t1
  30. WHERE t1.row > 1
  31. )

2.修改先remove再add的逻辑,去掉remove,直接add,但是在add入库的sql语句上做下整改:

  1. INSERT INTO t_centralized_mission_state ( "task_patrolled_id", "task_name", "task_progress" )
  2. VALUES
  3. ( '11111', 'task1', 100 ) ON conflict ( task_patrolled_id )
  4. DO UPDATE
  5. SET task_patrolled_id = '11111',
  6. "task_name" = 'task1',
  7. "task_progress" = '100'

其实就是运用了postgresql插入操作遇到唯一值重复时更新,这样只要两次add不是同一时间发生,第二次add就会覆盖第一次的add,保证数据库中数据的唯一性。

当然这只是权宜之计,其实可以将每次报文入库的逻辑,做成队列,队列每次只取一个来执行,这样就可以保证后一次操作和前一次操作不会冲突。

此文章只是为了记录“postgresql插入操作遇到唯一值重复时更新”的处理过程,仅供参考

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/836446
推荐阅读
相关标签
  

闽ICP备14008679号