oracle jdbc 邪恶数字"65536" —— 使用prepareStatement批量插入10万条记录引发的“血案”...

1.   故事背景:

mysql数据迁移到oracle,其中有个表名叫“bil_vip”,有10万条记录,迁移后检查发现oracle数据库只插入34464条记录,程序执行过程没有发现任何错误。修改数据库连接代码向mysql插入10万条记录,结果都插入OK

批量插入使用spring jdbctemplate.batchUpdate(sql, new BatchPreparedStatementSetter());方法,该方法的核心是PreparedStatementexecuteBatch方法。

2.   继续实验:

新建一个Test表,只有一个name字段做实验。

抛弃jdbctemplate,直接使用PreparedStatement做实验,结果和jdbcTemplate是一样的,实验证明总是会丢失65536条记录。

oracle 驱动的问题?换了最新driver,还是不行。继续探索....

3.   希望之光:

早上发了个消息向大家征求思路,继中说了一句分批处理,点亮了我的思路。按照继中提供思路,每1万条记录一批,分多批发送给Oracle

结果喜出望外,10万条记录全部插入成功。但是"65536"这个数字是什么意思呢......     

在网上搜索文章发现,这个65536是一个bug。当PreparedStatement批量处理正好65536个记录时候,程序会挂死。我试了一下真的挂死了,太吓人了,这坑够深的。

4.   解决方案:

spring jdbctemplate还是很好用的,而且业务已经被我封装了,如果使用PreparedStatement意味着多了一个处理分支,以后维护会很麻烦。

我新建一个MyJdbcTemplate类,继承 jdbctemplate类,并覆盖了batchUpdate方法。这下舒服了,系统又恢复了整洁。      

5.   结论和收获:

ü  有事多思考,多请教身边同事。

ü  坚持Open-close原则(Open for extension, Closed for modification)会系统更好的扩展,非常容易维护,关键是要坚持这个原则,如果我因为一个特殊分支使用了PreparedStatement,这样势必破坏了这个原则,日后的维护必然会很麻烦。

ü  基于oracle数据如果使用jdbc批量,一定要分批发送数据oracle,否则正好发一个65536系统就挂死,大于65536数据就丢失,杯具呀......

6.   题目何以为“血案”:

周二打球回家就想这个问题,打开笔记本调试,不知不觉搞到很晚,影响媳妇睡觉(媳妇早上5:30上班),被痛骂一顿,赶紧上床睡觉,我媳妇气的不行,手痛砸了一下床板(我们的床撤掉了床垫,只有床架和木板),床一下子塌了,把媳妇吓坏了,把我腿弄伤了一块,唉,“血案”呀。

 

 

 

更深入的文章:

NetworkClient PreparedStatement.executeBatch() hangs if batch is too large (ArrayIndexOutOfBoundsException in Network Server)

https://issues.apache.org/jira/browse/DERBY-428

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值