web-dev-qa-db-ja.com

基本-Hibernate / JDBC接続プールの問題のトラブルシューティング

基盤となる接続プールから取得するデータベース接続に関するHibernateの責任は何ですか。接続を使用する前に、接続が閉じているかどうかをテストしますか?もしそうなら、プールから別の接続を取得しますか?

以下にエラーと確認の情報を含めました。これのトラブルシューティングをどこから始められるかについてのアイデアは非常に役立ちます。また、使用しているSQLServerドライバー設定に関するアドバイスもあります。

カタリナログから:

 04-Nov-2010 21:54:52.691警告org.Apache.Tomcat.jdbc.pool.ConnectionPool.abandon接続が破棄されましたPooledConnection [ConnectionID:8]:Java.lang.Exception 
 org.Apache.Tomcat.jdbc.pool.ConnectionPool.getThreadDump(ConnectionPool.Java:926)
 at org.Apache.Tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.Java:681)
 at org.Apache.Tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.Java:545)
 at org.Apache.Tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.Java:166)
 org.Apache.Tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.Java:106)

アプリケーションログから:

 2010-11-04 21:54:52,705 [Tomcat-http--18]警告util.JDBCExceptionReporter-SQLエラー:0、SQLState:08S01 
 2010-11-04 21:54: 52,707 [Tomcat-http--18] ERRORutil.JDBCExceptionReporter-ソケットが閉じています
 2010-11-04 21:54:52,708 [Tomcat-http--18] ERRORtransaction.JDBCTransaction-JDBCロールバックに失敗しました
 Java.sql.SQLException:接続はすでに閉じられています。
 at org.Apache.Tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.Java:112)
 atorg.Apache。 Tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.Java:94)
 at org.Apache.Tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor.invoke(AbstractCreateStatementInterceptor.Java:71)
 org.Apache.Tomcat.jdbc.pool.interceptor.ConnectionState.invoke(ConnectionState.Java:132)[のorg.Apache.Tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.Java:94)
 ____。] at $ Proxy38.rollback(Unknown Source)
 at org.hibernate.transaction.JDBCTransa ction.rollbackAndResetAutoCommit(JDBCTransaction.Java:217)
 at org.hibernate.transaction.JDBCTransaction.rollback(JDBCTransaction.Java:196)
 at org.springframework.orm.hibernate3.HibernateTransactionManager.doRollback( HibernateTransactionManager.Java:676)
 at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.Java:845)
 at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(Abs Java:822)
 at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.Java:412)
 at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.Java: 111)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.Java:172)
 at org.springframework.aop.f ramework.Cglib2AopProxy $ DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.Java:625)

構成

<Resource defaultAutoCommit="false" defaultReadOnly="false"
        defaultTransactionIsolation="SERIALIZABLE"
        driverClassName="com.Microsoft.sqlserver.jdbc.SQLServerDriver"
        factory="org.Apache.Tomcat.jdbc.pool.DataSourceFactory"
        fairQueue="false" initialSize="10"
        jdbcInterceptors="ConnectionState;StatementFinalizer"
        jmxEnabled="true" logAbandoned="true" maxActive="100"
        maxIdle="10" maxWait="30000"
        minEvictableIdleTimeMillis="10000" minIdle="10"
        name="com.ourcompany.ap.shoppingcart/datasource"
        password="somePassword" removeAbandoned="true"
        removeAbandonedTimeout="60" testOnBorrow="true"
        testOnReturn="false" testWhileIdle="false"
        timeBetweenEvictionRunsMillis="5000"
        type="javax.sql.DataSource"
        url="jdbc:sqlserver://approd\approd;databaseName=prod"
        useEquals="false" username="AccessPointNet"
        validationInterval="30000" validationQuery="SELECT 1"/>`
15
BuddyJoe

基盤となる接続プールから取得するデータベース接続に関するHibernateの責任は何ですか。

それほど多くはありませんが、Sessionが閉じられたときにリリースします。

接続を使用する前に、接続が閉じているかどうかをテストしますか?もしそうなら、プールから別の接続を取得しますか?

いいえ、Hibernateは行いません。必要に応じて、接続の有効性を確認するのは接続プールの責任です。

以下にエラーと確認の情報を含めました。これのトラブルシューティングをどこから始められるかについてのアイデアは非常に役立ちます。

正確にはどのようなプロセスを実行していますか?長い取引?タイムアウトしますか? Caused by:は何と言っていますか?トレースについて:

 2010-11-04 21:54:52,705 [Tomcat-http--18]警告util.JDBCExceptionReporter-SQLエラー:0、SQLState:08S01 
 2010-11-04 21:54: 52,707 [Tomcat-http--18]エラーutil.JDBCExceptionReporter-ソケットが閉じられました
 2010-11-04 21:54:52,708 [Tomcat-http--18]エラーtransaction.JDBCTransaction-JDBCロールバックが失敗しましたJava.sql .SQLException:接続はすでに閉じられています。

決定論的な方法でそれを再現できますか?ネットワークの問題はありますか?

また、使用しているSQLServerドライバー設定に関するアドバイスもあります。

以下に、Tomcatと接続プールの構成に関する優れたリソースを追加しました。ただし、SQLServerに固有のものではありません。

リソース

14
Pascal Thivent

removeAbandonedTimeout値をより高い数値に増やすことで解決された同様の問題がありました。私たちが直面した問題は、上記のタイムアウトよりも長い時間がかかったクエリが原因でした。

17
Cid

通常、これを回避するには、dbcpを使用し、データソースを定義するときにvalidationQueryを提供します。次に、dbcpは、プールされた接続をアプリケーションに返す前に、そのクエリを発行して(接続が機能しなくなった場合は透過的に再作成して)、プールされた接続のユーザビリティを検証します。

詳細については、 http://Tomcat.Apache.org/Tomcat-6.0-doc/jndi-datasource-examples-howto.html を確認してください。

2
meriton

現在、プロジェクトでliquibase(v1.9)を使用していますが、changeSetsが空白のスキーマに対して実行されると、常に60秒以上かかり、スレッドが放棄されたとマークされます。removeAbandonedTimeout valueですが、これはこの問題を防ぐために私が見つけた唯一の解決策です。ただし、最初のスキーマの作成が完了した後、これが問題になることはめったにないため、値を60秒に戻しました。

2
mjj1409

私は過去に、接続をプールに正しく戻さなかった問題に取り組みました。そのため、接続が使用されて返されなかった場合、タイムアウト時にデータベース呼び出しを行うと例外がスローされます。

データベースを呼び出すことで問題を再現し、8時間待機して(postgresのデフォルトのタイムアウト)、データベースを再度呼び出しようとしました。毎回同じ例外をスローします。私たちの解決策は、接続管理戦略を再考することでした(または、さらに良いことに、add)。

つまり、要約すると、セッションを閉じて実際に接続をプールに戻しているのでしょうか。

1
Jeremy

上記の例外の解決策を得ました。セッションを閉じている間、セッションファクトリのインスタンスも閉じるだけです。

以下のコードを見てください:

public class HibernateUtil {
    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
        }
        catch (Throwable ex) {
            ex.printStackTrace();
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionfactory() {
        return sessionFactory;
    }

    public static Session getSession() {
        Session session=sessionFactory.openSession();
        session.getTransaction().begin();
        return session;
    }
    public static void closeSession(Session session) {
        if(session!=null )
        {
            if(session.getTransaction().isActive())
            {
                session.getTransaction().commit();
            }
                session.close();
                getSessionfactory().close();
        }
    }
}

メソッドを呼び出すだけですHibernateUtil.closeSession()。これで問題は解決します。

0
user3247321