oracle jdbc 邪惡數字"65536" ---批量插入10萬條記錄引起的「血案」

1.   故事背景: mysql

mysql數據遷移到oracle,其中有個表名叫「bil_vip」,有10萬條記錄,遷移後檢查發現oracle數據庫只插入34464條記錄,程序執行過程沒有發現任何錯誤。修改數據庫鏈接代碼向mysql插入10萬條記錄,結果都插入OK。 spring

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

2.   繼續實驗: 數據庫

新建一個Test表,只有一個name字段作實驗。 oracle

拋棄jdbctemplate,直接使用PreparedStatement作實驗,結果和jdbcTemplate是同樣的,實驗證實老是會丟失65536條記錄。 spa

oracle 驅動的問題?換了最新driver,仍是不行。繼續探索.... 調試

3.   但願之光: 繼承

早上發了個消息向你們徵求思路,繼中說了一句分批處理,點亮了個人思路。按照繼中提供思路,每1萬條記錄一批,分多批發送給Oracle。 ip

結果喜出望外,10萬條記錄所有插入成功。可是"65536"這個數字是什麼意思呢......      io

在網上搜索文章發現,這個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上班),被痛罵一頓,趕忙上牀睡覺,我媳婦氣的不行,手痛砸了一下牀板(咱們的牀撤掉了牀墊,只有牀架和木板),牀一會兒塌了,把媳婦嚇壞了,把我腿弄傷了一塊,唉,「血案」呀。

相關文章
相關標籤/搜索