2009-01-21 62 views
0

我有以下代碼:奇怪的JDBC的executeQuery異常

public Object RunQuery(String query) throws Exception{ 
    System.out.println("Trying to run query"); 
    Statement stmt = null; 
    ResultSet rs = null; 
    try { 
     stmt = conn.createStatement(); 
     System.out.println("Got Statement"); 
     rs = stmt.executeQuery(query); 
     System.out.println("Query executed"); 
     ... 


    } catch (SQLException ex) { 
     // handle any errors 
     System.out.println("SQLException: " + ex.getMessage()); 
     System.out.println("SQLState: " + ex.getSQLState()); 
     System.out.println("VendorError: " + ex.getErrorCode()); 
    } 
    catch (Exception ex) { 
     System.out.println("Exception: " + ex.getMessage()); 
    } 
    finally { 
     if (rs != null) { 
      try { 
       rs.close(); 
      } catch (SQLException sqlEx) { 
      } // ignore 
      rs = null; 
     } 
     if (stmt != null) { 
      try { 
       stmt.close(); 
      } catch (SQLException sqlEx) { 
      } // ignore 
      stmt = null; 
     } 
     return ret; 
    } 
} 

運行

query = "SELECT * FROM smalltable" 

當這工作完全正常,但未能上

query = "SELECT * FROM bigtable" 

擁有大約200K記錄。 調試器優雅地忽略catch塊並直接進入finally塊; NetBeans的給了我這個堆棧幀的時候我加入stmt.executeQuery(查詢)到監視列表:在這個框架

>Exception occurred in target VM: Communications link failure Last packet sent to the server was 0 ms ago. 
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure Last packet sent to the server was 0 ms ago. 

at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 

at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) 

at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) 

at java.lang.reflect.Constructor.newInstance(Constructor.java:513) 

at com.mysql.jdbc.Util.handleNewInstance(Util.java:406) 

at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1074) 

at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3009) 

at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2895) 

at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3438) 

at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1951) 

at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2101) 

at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2548) 

at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2477) 

at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1422) 

at RunQuery 
Caused by: java.net.SocketException: Software caused connection abort: recv failed 

at java.net.SocketInputStream.socketRead0(Native Method) 

at java.net.SocketInputStream.read(SocketInputStream.java:129) 

at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:157) 

at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:188) 

at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2452) 

at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2962) 

... 9 more 




我該怎麼辦大型查詢?



編輯:我使用J連接器和MySQL服務器5.1;連接字符串是

jdbc:mysql://localhost?user=root&password=password 

是的,我知道,選擇*是一種不好的做法,但你可以看到我剛剛開始,這是或多或少第二次測試我做

+0

您正在使用哪個jdbc驅動程序?另外,你通常應該避免選擇*查詢。 – kgiannakakis 2009-01-21 12:51:04

回答

1

唯一我能想到的事情會導致差異是某種網絡級超時,Netbeans輸出肯定會指向這個方向。什麼是您正在使用的JDBC連接字符串;也許有一個超時參數可以被提起?

如果問題依然存在,並且看到在該級別的通信是什麼,那麼也可能需要插入網絡數據包嗅探器。在短期和長期查詢中發揮「發現差異」的作用,你可能會很清楚在另一個成功的情況下失敗的原因。

(一般來說select *是一個壞主意,僅僅是因爲所有額外的數據不必要地回收,在這種情況下,從大表中的所有行中選擇所有列顯然會給連接帶來麻煩,我知道在這種情況下,你的問題仍然有效,因爲有時你可能需要這樣做,除了選擇一個更大的表的子集可能會做同樣的事情,但我只是指出這一點如果您在生產中將此作爲快捷方式使用,則一般指導原則)。

1

我的直接想法是,在獲取所有數據時可能存在內存問題。我不知道MySQL是如何爲此設置的,但您可能想要嘗試在ResultSet中設置提取大小或通過選擇較少的列來限制ResultSet大小。 JDBC驅動程序可能試圖在一次操作中獲取整個表。

請注意,請不要做stmt.executeQuery(查詢)。始終使用PreparedStatement並綁定查詢參數。在你的例子中沒有參數,但這是一種對安全性至關重要的做法。切勿使用帶有'文字'參數的SQL(例外情況是文字是受信任的字符串,例如代碼中的常量或非字符串類型,例如已經解析的數字)。

0

如果它直接跳到finally,那麼拋出其他代碼的「異常」實際上是Error的後代?這會避免你完全抓住。

你可能得到了一個OutOfMemoryError,然後得到了網絡異常,因爲OOME關閉了一些東西?