亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用MySQL流式傳輸大型結果集

使用MySQL流式傳輸大型結果集

絕地無雙 2019-11-28 10:10:22
我正在開發一個使用大型MySQL表的spring應用程序。加載大表時,我得到一個OutOfMemoryException,因為驅動程序試圖將整個表加載到應用程序內存中。我嘗試使用statement.setFetchSize(Integer.MIN_VALUE);但是然后我打開的每個ResultSet都掛了close(); 在網上查找時,我發現發生這種情況是因為它嘗試在關閉ResultSet之前嘗試加載所有未讀的行,但事實并非如此,因為我這樣做是:ResultSet existingRecords = getTableData(tablename);try {    while (existingRecords.next()) {        // ...    }} finally {    existingRecords.close(); // this line is hanging, and there was no exception in the try clause}小表(3行)也會發生掛起,如果我不關閉RecordSet(在一種方法中發生),則會connection.close()掛起。掛起的堆棧跟蹤:SocketInputStream.socketRead0(FileDescriptor,byte [],int,int,int)行:不可用[本機方法]SocketInputStream.read(byte [],int,int)行:129ReadAheadInputStream.fill(int)行:113ReadAheadInputStream。 readFromUnderlyingStreamIfNecessary(byte [],int,int)行:160ReadAheadInputStream.read(byte [],int,int)行:188MysqlIO.readFully(InputStream,byte [],int,int)行:2428 MysqlIO.reuseAndReadPacket(Buffer ,int)行:2882MysqlIO.reuseAndReadPacket(Buffer)行:2871MysqlIO.checkErrorPacket(int)行:3414MysqlIO.checkErrorPacket()行:910MysqlIO.nextRow(Field [],int,boolean,int,boolean,boolean,布爾值,緩沖區)行:1405RowDataDynamic.nextRecord()行:413RowDataDynamic.next()行:392 RowDataDynamic.close()行:170JDBC4ResultSet(ResultSetImpl).realClose(boolean)行:7473 JDBC4ResultSet(ResultSetImpl).close()行:881 DelegatingResultSet.close ()行:152DelegatingResultSet.close()行:152DelegatingPreparedStatement(DelegatingStatement).close()行:163(這是我的課程)Database.close()行:84
查看完整描述

3 回答

?
qq_花開花謝_0

TA貢獻1835條經驗 獲得超7個贊

僅設置獲取大小不是正確的方法。的javadocStatement#setFetchSize()已經聲明以下內容:


向JDBC驅動程序提示應從數據庫中獲取的行數


驅動程序實際上可以自由地應用或忽略提示。一些驅動程序忽略它,一些驅動程序直接應用它,一些驅動程序需要更多參數。MySQL JDBC驅動程序屬于最后一類。如果查看MySQL JDBC驅動程序文檔,將看到以下信息(向下滾動約2/3,直到標題ResultSet為止):


要啟用此功能,您需要通過以下方式創建一個Statement實例:


stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY);

stmt.setFetchSize(Integer.MIN_VALUE);

請閱讀文檔的整個部分,它也描述了這種方法的注意事項。這是一個相關的引用:


這種方法有一些警告。您必須先讀取(或關閉)結果集中的所有行,然后才能對連接發出任何其他查詢,否則將引發異常。


(...)


如果該語句在事務范圍內,則在事務完成時釋放鎖(這意味著該語句需要先完成)。與大多數其他數據庫一樣,在讀取該語句上所有未決的結果或關閉該語句的活動結果集之前,該語句是不完整的。


如果不能解決OutOfMemoryError(not Exception)問題,則可能是您將所有數據存儲在Java內存中,而不是在數據輸入后立即進行處理。這可能需要對代碼進行更多更改,也許完全重寫。在此之前,我已經回答了類似的問題。


查看完整回答
反對 回復 2019-11-28
?
智慧大石

TA貢獻1946條經驗 獲得超3個贊

不要關閉ResultSet兩次。


顯然,當關閉a時,Statement它嘗試關閉相應的ResultSet,如您在堆棧跟蹤的這兩行中所見:


DelegatingResultSet.close()行:152

DelegatingPreparedStatement(DelegatingStatement).close()行:163


我原以為掛斷電話了,ResultSet.close()但實際上是掛斷Statement.close()電話的地方ResultSet.close()。由于ResultSet已經關閉,因此它剛剛掛起。


我們用替換了所有ResultSet.close(),results.getStatement().close()并刪除了所有Statement.close(),現在問題已解決。


查看完整回答
反對 回復 2019-11-28
  • 3 回答
  • 0 關注
  • 1143 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號