web-dev-qa-db-ja.com

WebApp(Tomcat-jdbc)破棄された例外をスローするプールされたDB接続

私はしばらくの間SOを参照していて、その過程で私の帽子をかみ砕きましたが、私の問題に完全に一致するものを見つけることができません。
略して、非アクティブ状態が60秒間続くと、優れたスタックトレース(org.Apache.Tomcat.jdbc.pool.ConnectionPoolが破棄される)を取得します。これは、サーバー側のスレッドのカップルの通常の動作です。
Tomcat JDBC接続プール(org.Apache.Tomcat.jdbc.pool.DataSource)を直接使用しています
スタックトレース:

 2012年10月29日8:55:50 PM org.Apache.Tomcat.jdbc.pool.ConnectionPool abandon 
警告:接続が破棄されましたPooledConnection [com .mysql.jdbc.JDBC4Connection @ 1ad2916]:Java.lang.Exception 
 at org.Apache.Tomcat.jdbc.pool.ConnectionPool.getThreadDump(ConnectionPool.Java:967)
 at org.Apache .Tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.Java:721)
 at org.Apache.Tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.Java:579)
 at org .Apache.Tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.Java:174)
 at org.Apache.Tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.Java:111)
 com.getsom.getConnection(DAO.Java:1444)
 at com.getsom.PreparedConnection。(PreparedConnection.Java:48)
 at com.getsom.Alarms.run(Alarms.Java: 492)

私のPoolPropertiesは次のように構成されています。

    PoolProperties pp = new PoolProperties();

    pp.setUrl( someValidUrl);
    pp.setDriverClassName("com.mysql.jdbc.Driver");
    pp.setUsername( someUser);
    pp.setPassword( somePassword);
    pp.setJmxEnabled( true);
    pp.setTestWhileIdle( true);
    pp.setTestOnBorrow( true);
    pp.setValidationQuery( "SELECT 1");
    pp.setTestOnReturn( false);
    pp.setValidationInterval(30000);
    pp.setTimeBetweenEvictionRunsMillis(30000);
    pp.setMaxActive(100);
    pp.setInitialSize(10);
    pp.setMaxWait(10000);
    pp.setMinEvictableIdleTimeMillis(30000);
    pp.setMinIdle(10);

    pp.setLogAbandoned(true);
    pp.setRemoveAbandoned(true);
    pp.setRemoveAbandonedTimeout(60);
    pp.setJdbcInterceptors("org.Apache.Tomcat.jdbc.pool.interceptor.ConnectionState;"+
      "org.Apache.Tomcat.jdbc.pool.interceptor.StatementFinalizer");    

    setPoolProperties(pp);

接続のライフサイクルでは30秒はそれほど長くないので、setValidationInterval(30000)が節約になることを期待していました。とにかく質問は:
この接続を永続的に維持するために何が不足していますか?
知っておきたいこと:30秒前に呼び出されたのに、接続を要求した関数でタイムアウトになるのはなぜですか。

21
MonoThreaded

このページにアクセスするのに1年以上遅れていますが、同様の問題が発生していて解決策も必要だったため、ここでつまずきました。だから私は私が最終的に私のために働いたものを共有したいと思いました。

私の場合、この記事を見つけて読んだ後>>> configuring-jdbc-pool-high-concurrency -このようなインターセプターをプール構成に追加しました。

_"org.Apache.Tomcat.jdbc.pool.interceptor.ResetAbandonedTimer"
_

そのため、(上記の投稿したコードから)setJdbcInterceptors(...)を実行する行は次のようになります。

_p.setJdbcInterceptors(
            "org.Apache.Tomcat.jdbc.pool.interceptor.ConnectionState;"
            + "org.Apache.Tomcat.jdbc.pool.interceptor.StatementFinalizer;"
            + "org.Apache.Tomcat.jdbc.pool.interceptor.ResetAbandonedTimer");
_

説明-記事からの引用によると、

接続がまだ使用されていることを検出したら、タイムアウトタイマーをリセットして、接続が破棄されたと見なされないようにします。これを行うには、インターセプターを挿入します。

ステートメントが準備されるかクエリが実行されるたびに、タイマーは接続プールの破棄タイマーをリセットします。このように...多くのクエリと更新を行うと、タイムアウトしません。

かなり前に問題を克服した可能性が高いことを念頭に置いて、私がそうしたように、これがこのページにぶつかる同様の問題を抱えている他の人に役立つことを願っています。

乾杯!

46
techknowcrat

リソースタグが存在する場所であれば、Tomcat7のconf/server.xmlまたはcontext.xmlに以下のエントリを追加するだけです。

jdbcInterceptors="org.Apache.Tomcat.jdbc.pool.interceptor.ConnectionState;
org.Apache.Tomcat.jdbc.pool.interceptor.StatementFinalizer;
org.Apache.Tomcat.jdbc.pool.interceptor.ResetAbandonedTimer"
4
Patrikoko

TomcatのWebサイトで PoolConnection に関する情報を見たことはありますか。おそらく、必要なのはプロパティminEvictableIdleTimeMillisを調べることです。

あなたの質問に答えるために、30秒ごとにアイドル接続と放棄の接続をチェックしているため(TimeBetweenEvictionRunsMillisを参照)、30秒で強制排除アイドルタイムアウトを設定しているため(minEvictableIdleTimeMillisを参照)、タイムアウトになります。その後、あなたはあなたが持っているもので終わります。アイドル中にこの例外を受け取っているとのことですが、この例外は、接続を放棄するのではなく、アイドル接続を閉じた結果だと思います。私の理解では、接続を放棄することは、(アイドル接続ではなく)予想よりも長いクエリのタイムアウトに使用されます。

個人的には、接続(つまり、dbへの接続)を不必要に消費しているため、接続を永久に存続させたくありません。最大接続数、エビクション実行数、アイドル時間をいじって、自分の要件に合わせて最適化しました。私はあなたがこれらの値をほぼ永遠に保つのに十分な大きさに設定できると思います!それは本当にあなたがやっていることに依存します...

申し訳ありませんが、ここではこれ以上の助けはできませんでした。

4
ramsinb

Tomcatのcontext.xmlでデータソースを定義する場合は、以下のようにResetAbandonedTimerを追加する必要があります。

jdbcInterceptors="ConnectionState;StatementFinalizer;ResetAbandonedTimer"

ResetAbandonedTimerを設定した後、アプリケーションで問題が解決しました。ResetAbandonedTimerインターセプターとremoveAbandoned = "true" removeAbandonedTimeout = "60"の間に関係があることを通知するように要求しています

1
rajesh chaganti

設定ファイルで「removeAbandonedTimeout」を追跡します。これは、アプリケーションでの最大実行クエリでなければなりません。それ以外の場合は、実行の途中で接続を閉じます

1
ravindra

このスレッドが古いのを確認できますが、同様の問題があり、最終的にその原因を見つけたので、誰かを助けることができるかどうか共有したいと思います。

落ち着いたWebサービスからの接続を使用しました。クライアントからのリクエストを処理するサーバー側のインターフェイスで、メソッドシグネチャに誤って「スローIOException」を挿入しました。

@GET
@Path("/databases")
@Produces(MediaType.APPLICATION_JSON)
public String getAllDatabases() throws IOException {
0

同様の問題がありました。つまり、トランザクションに時間がかかっていたために放棄されたため、TomcatはJDBC接続を閉じていました。

abandonedidleが異なることを認識し、次のように設定することで解決しました:spring.datasource.Tomcat.removeAbandonedTimeout: 86400 #seconds

0
Mate Šimović

この質問への回答は私にとって非常に役に立ちました。

私の場合でも、「ResetAbandonedTimer」JDBCインターセプターはすでに構成されています。

しかし、私が設定した「removeAbandonedTimeout」よりも長く実行されるクエリがありました。 「removeAbandonedTimeout」を増やすと、問題はなくなりました。

0
buzz