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 阅读(...) 评论(...) 编辑 收藏
刷新评论刷新页面返回顶部