4

最近、私のトムキャットがハングアップし始めました。リクエストは返信されませんでした。接続が接続プールに返されないことが原因であることがわかりました。

c3p0 を hibernate で使用しており、データベースは mysql 5.5 です。

接続リークをデバッグするために、次のプロパティをhibernate.cfg.xml

 <property name="hibernate.c3p0.unreturnedConnectionTimeout">30</property>
        <property name="hibernate.c3p0.debugUnreturnedConnectionStackTraces">true</property>

それらを追加した後、ログに次のように表示されます:

[2013-10-12 23:40:22.487] [ INFO] BasicResourcePool.removeResource:1392 - A checked-out resource is overdue, and will be destroyed: com.mchange.v2.c3p0.impl.NewPooledConnection@1f0c0dd
[2013-10-12 23:40:22.487] [ INFO] BasicResourcePool.removeResource:1395 - Logging the stack trace by which the overdue resource was checked-out.
java.lang.Exception: DEBUG ONLY: Overdue resource check-out stack trace.

を指していますat dao.DAOBasicInfo.getBean(DAOBasicInfo.java:69)

public static Basicinfo getBean(Integer iduser) {
        Basicinfo u = null;
        Session sess = NewHibernateUtil.getSessionFactory().openSession();
        try {
            Transaction tx = sess.beginTransaction();   //line 69
            Query q = sess.createQuery("from Basicinfo where iduser=" + iduser);
            u = (Basicinfo) q.uniqueResult();
            if (u == null) {
                u = new Basicinfo();
                u.setIduser(iduser);
            }
            tx.commit();
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            sess.close();
        }
        return u;
    }

クロスチェックしたところ、 Mysql は InnoDB とのトランザクションをサポートしていると言っています

上記のエラーが原因で、接続が返されず、接続が積み重なってアプリが応答しなくなります。

トランザクションを開始する際に何が問題なのか教えてください。私はfinallyを使用していますが、例外はスローされません。

4

2 に答える 2

4

それをデバッグするためのいくつかの提案

  • スティーブがコメントで述べたように。unreturnedConnectionTimeout オプションを削除するとどうなるかを確認してください。

  • クエリに時間がかかりすぎている可能性があります。コードのパフォーマンス統計を記録して、クエリにかかる時間を確認してください。クエリを調整する必要があるかもしれません。また、短期的には、unreturnedConnectionTimeout をクエリの応答時間より長くすることもできます。

  • また、休止状態でトランザクション タイムアウト オプションを試してください。tx.setTimeout(20) を設定して、タイムアウト値を調整し、一部のクエリがタイムアウトするかどうかを確認します。

  • プロファイリング ツールを使用することもできます。Java バージョンがサポートされている場合は、VisualVMを試してください。それ以外の場合 (Linux または Mac の場合) 、Java の古いバージョンでJava Debugging コマンドを試してみることをお勧めします。これらのコマンドの一部は、JDK からも入手できます。

コードの小さな改善

  • 問題が本当に解決するかどうかはわかりませんが、トランザクションのロールバックを例外ブロックに追加することをお勧めします。別の例外を回避するために、tx.close に別の try catch を追加しました。

  • また、セッション クローズの null チェックを追加しました。finally ブロックで別の例外がスローされた場合、finally の 1 つの条件が完全に実行されない可能性があることは既にご存じかもしれません。現在、コードに適用できない場合がありますが、finally ブロックに複数の行を追加する場合は、次の行が実行できるように例外がカバーされていることを確認してください。

  • もう 1 つの提案は、トランザクション自体の範囲を縮小することです。コードを見ると、uid が見つからない場合にのみトランザクションが必要になるようです。if(u==null) ブロック内のトランザクション コードを制限するのはどうですか。役立つかどうかはわかりませんが、読み取り用のトランザクションは必要ありません。

以下は私のサンプルコードです

    public static Basicinfo getBean(Integer iduser) {
    Basicinfo u = null;
    Transaction tx = null;
    Session sess = NewHibernateUtil.getSessionFactory().openSession();
    try {

        Query q = sess.createQuery("from Basicinfo where iduser=" + iduser);
        u = (Basicinfo) q.uniqueResult();
        if (u == null) {
            tx = sess.beginTransaction();   //line 69
            u = new Basicinfo();
            u.setIduser(iduser);
            tx.commit();
        }           
    } catch (Exception ex) {
        ex.printStackTrace();
        if(tx != null) {
            try {
             tx.rollback();
            } catch(Exception e){e.printStackTrace;}
        }
    } finally {
        if(sess!=null) {
         sess.close();
        }
    }
    return u;
}
于 2013-10-14T16:53:58.223 に答える
2

このエラーが発生する理由の 1 つは、次のことを確認していない場合です。

transaction.commit();

この質問への回答ではありませんが、コミットするのを忘れた人も、エラーをグーグル検索した後にこのページに到達します

于 2014-05-07T07:01:05.067 に答える