天天看点

JDBC操作数据库报 Duplicate entry

JDBC操作数据库报 Duplicate entry

现象:

  在日常开发中经常使用jdbc直连数据库操作,难免会遇到 Duplicate entry的错误。先直接说问题原因:

     1. 绝大多数情况下该错误是由于重复插入导致的

     2. 数据库外键约束创建不当引起

场景:

  结合楼主在实际开发中遇到的问题简单说一下,系统采用canal监听binlog源源不断的将增量数据使用jdbc保存至数据库,事件类型包括增删改,采用多线程并行处理数据。

  在实际场景中,楼主遇到程序不断的刷 Duplicate entry,起初以为是canal在重启后会回溯一段binlog导致的重复消费,可是等了好久还在刷,意识到这肯定是代码的bug了。

  最终找到了原因所在: 对每一个事件进行解析并拼接sql,如果是连续insert则采取批量处理,然后将sql信息缓存到当前线程的ThreadLocal中,然后入库,乍一看没啥问题,毕竟ThreadLocal为新开启一个线程单独分配副本,那问题出在哪里呢?最终发现代码使用了                                              线 程池技术,也就是说一个线程用完后不会立马关闭,会被回收等待下次使用,当两条连续的业务数据公用一个线程时就出问题了,后面的业务线会把上一条业务线的数据重复消费,重温导致了不断刷 Duplicate entry 的错误。解决办法就是                                               每次业务处理完成清空ThreadLocal缓存。

  到这儿还没结束,经过上面的额修改确实异常数量降低了不少,可是还是在报 Duplicate entry 的错误,只不过是偶尔出现。最终发现是数据库中某张表设置了外键,把外键取消掉就好了

总结:

  1. 每条业务线处理完清楚当前线程的ThreadLocal缓存

  2. 每条insert语句加上 ignore,例如 insert ignore into t....

  3. 数据库层面删除不合理的外键约束

  

  

posted on 2019-05-29 10:44 cq_fuqq 阅读(...) 评论(...) 编辑 收藏

刷新评论刷新页面返回顶部

继续阅读