0

次のコードがあります。

 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 ブロックに直接進みます。stmt.executeQuery(query) を監視リストに追加すると、NetBeans から次のスタック フレームが返されました。

>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

はい、 select * が悪い習慣であることは知っていますが、ご覧のとおり、私はまだ始めたばかりで、これは多かれ少なかれ私が行っている 2 番目のテストです。

4

3 に答える 3

1

私の即時の考えは、そのすべてのデータをフェッチする際にメモリの問題が発生する可能性があるということです。この目的のために MySQL がどのように設定されているかはわかりませんが、ResultSet でフェッチ サイズを設定するか、選択する列を少なくして ResultSet のサイズを制限してみてください。JDBC ドライバーが 1 回の操作でテーブル全体を取得しようとしている可能性があります。

ちなみに、stmt.executeQuery(query) は絶対にしないでください。常に PreparedStatement を使用し、クエリ パラメータをバインドします。あなたの例にはパラメーターはありませんが、これはセキュリティ上の重要な慣行です。「リテラル」であるパラメーターを使用して SQL を使用しないでください (例外は、リテラルが、コードの定数などの信頼できる文字列である場合や、既に解析した数値などの非文字列型である場合です)。

于 2009-01-21T14:31:28.050 に答える
1

私が考えることができる唯一の違いは、ある種のネットワークレベルのタイムアウトであり、Netbeans の出力は確かにこの方向を指しています。使用している JDBC 接続文字列は何ですか? おそらく、バンプできるタイムアウトパラメータがありますか?

問題が解決しない場合は、ネットワーク パケット スニファーを接続して、そのレベルでの通信がどのようなものかを確認することも価値があるかもしれません。短いクエリと長いクエリを使用して「違いを見つける」と、一方が失敗し、他方が成功する理由がよくわかるかもしれません。

(一般select *に、不必要に余分なデータが返されるという理由だけで、悪い考えです。この場合、大きなテーブルのすべての行からすべての列を選択すると、小さなテーブルから選択する場合と比較して、明らかに接続の問題が発生します。私はこの場合、これを行う必要がある場合があるため、質問はまだ有効であることを知っておいてください。また、さらに大きなテーブルのサブセットを選択すると、おそらく同じことが行われる可能性がありますが、これは一般的なガイドラインとして指摘しているだけです。これを本番環境でショートカットとして使用していました。)

于 2009-01-21T12:53:10.323 に答える
0

最終的に直接スキップしている場合、他のコード内でスローされている「例外」は実際にエラーの子孫ですか? それはあなたのキャッチを完全に避けるでしょう.

OutOfMemoryError が発生した後、OOME が何かを閉じたためにネットワーク例外が発生した可能性がありますか?

于 2009-01-28T01:46:37.830 に答える