基础知识 - Hibernate / JDBC 连接池问题故障排除

发布于 2024-10-01 07:48:10 字数 3891 浏览 3 评论 0原文

Hibernate 对于从底层连接池获取的数据库连接的责任是什么。它是否在使用连接之前测试连接是否已关闭?如果是的话,从池中获取另一个连接?

我在下面包含了错误和确认信息。任何关于我可以从哪里开始解决这个问题的想法都会非常有帮助。以及有关我们正在使用的 SQL Server 驱动程序设置的任何建议。

来自 Catalina 日志:

04-Nov-2010 21:54:52.691 WARNING org.apache.tomcat.jdbc.pool.ConnectionPool.abandon Connection has been abandoned PooledConnection[ConnectionID:8]:java.lang.Exception
    at 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)
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:106)

来自我们的应用程序日志:

2010-11-04 21:54:52,705 [tomcat-http--18] WARN  util.JDBCExceptionReporter  - SQL Error: 0, SQLState: 08S01
2010-11-04 21:54:52,707 [tomcat-http--18] ERROR util.JDBCExceptionReporter  - Socket closed
2010-11-04 21:54:52,708 [tomcat-http--18] ERROR transaction.JDBCTransaction  - JDBC rollback failed
java.sql.SQLException: Connection has already been closed.
    at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:112)
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:94)
    at org.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor.invoke(AbstractCreateStatementInterceptor.java:71)
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:94)
    at org.apache.tomcat.jdbc.pool.interceptor.ConnectionState.invoke(ConnectionState.java:132)
    at $Proxy38.rollback(Unknown Source)
    at org.hibernate.transaction.JDBCTransaction.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(AbstractPlatformTransactionManager.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.framework.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"/>`

What is Hibernate's responsibility in regards to database connections it gets from an underlying connection pool. Does it test to see if a connection is closed before it uses it? and if so get another connection from the pool?

I've included error and confirmation info below. Any ideas of where I can start to troubleshoot this would be very helpful. And any advice on the SQL Server driver settings we are using.

from the Catalina log:

04-Nov-2010 21:54:52.691 WARNING org.apache.tomcat.jdbc.pool.ConnectionPool.abandon Connection has been abandoned PooledConnection[ConnectionID:8]:java.lang.Exception
    at 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)
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:106)

from our application log:

2010-11-04 21:54:52,705 [tomcat-http--18] WARN  util.JDBCExceptionReporter  - SQL Error: 0, SQLState: 08S01
2010-11-04 21:54:52,707 [tomcat-http--18] ERROR util.JDBCExceptionReporter  - Socket closed
2010-11-04 21:54:52,708 [tomcat-http--18] ERROR transaction.JDBCTransaction  - JDBC rollback failed
java.sql.SQLException: Connection has already been closed.
    at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:112)
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:94)
    at org.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor.invoke(AbstractCreateStatementInterceptor.java:71)
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:94)
    at org.apache.tomcat.jdbc.pool.interceptor.ConnectionState.invoke(ConnectionState.java:132)
    at $Proxy38.rollback(Unknown Source)
    at org.hibernate.transaction.JDBCTransaction.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(AbstractPlatformTransactionManager.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.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:625)

The configuration:

<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"/>`

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

み格子的夏天 2024-10-08 07:48:10

我遇到了类似的问题,通过将 removeAbandonedTimeout 值增加到更高的数字来解决。我们遇到的问题是由于查询花费的时间比上述超时时间更长。

I had a similar problem which was solved by increasing the removeAbandonedTimeout value to a higher number. The problem we faced was due to the query which took longer time that the above mentioned timeout.

執念 2024-10-08 07:48:10

Hibernate 对于从底层连接池获取的数据库连接的责任是什么。

不多,当 Session 关闭时释放它。

它是否在使用连接之前测试连接是否已关闭?如果是的话,从池中获取另一个连接?

不,Hibernate 不会,如果您愿意的话,检查连接的有效性是连接池的责任。

我在下面添加了错误和确认信息。任何关于我可以从哪里开始解决这个问题的想法都会非常有帮助。

你到底在运行什么样的进程?一笔长期交易?是否超时? Caused by: 说什么?关于跟踪:

2010-11-04 21:54:52,705 [tomcat-http--18] WARN util.JDBCExceptionReporter - SQL Error: 0, SQLState: 08S01 
2010-11-04 21:54:52,707 [tomcat-http--18] ERROR util.JDBCExceptionReporter - Socket closed
2010-11-04 21:54:52,708 [tomcat-http--18] ERROR transaction.JDBCTransaction - JDBC rollback failed java.sql.SQLException: Connection has already been closed.

你能以确定性的方式重现它吗?有网络问题吗?

以及有关我们正在使用的 SQL Server 驱动程序设置的任何建议。

我在下面添加了有关 Tomcat 和连接池配置的精彩资源。但并非特定于 SQL Server。

资源

What is Hibernate's responsibility in regards to database connections it gets from an underlying connection pool.

Not much, releasing it when the Session gets closed.

Does it test to see if a connection is closed before it uses it? and if so get another connection from the pool?

No, Hibernate doesn't, checking the validity of connection(s) is the responsibility of a connection pool if you want to.

I've included error and confirmation info below. Any ideas of where I can start to troubleshoot this would be very helpful.

What kind of process are you running exactly? A long transaction? Does it timeout? What does the Caused by: say? About the trace:

2010-11-04 21:54:52,705 [tomcat-http--18] WARN util.JDBCExceptionReporter - SQL Error: 0, SQLState: 08S01 
2010-11-04 21:54:52,707 [tomcat-http--18] ERROR util.JDBCExceptionReporter - Socket closed
2010-11-04 21:54:52,708 [tomcat-http--18] ERROR transaction.JDBCTransaction - JDBC rollback failed java.sql.SQLException: Connection has already been closed.

Can you reproduce it in a deterministic way? Any networking problem?

And any advice on the SQL Server driver settings we are using.

I've added a great resource about Tomcat and connection pool configuration below. Not specific to SQL Server though.

Resources

知你几分 2024-10-08 07:48:10

我们通常通过使用 dbcp 来解决这个问题,并在定义数据源时提供validationQuery。然后,dbcp 将通过发出该查询来验证池连接的可用性(如果连接不再工作,则透明地重新创建连接),然后将它们返回给应用程序。

查看
http://tomcat.apache.org/tomcat-6.0 -doc/jndi-datasource-examples-howto.html
了解更多详情。

We usually work around this by using dbcp, and providing a validationQuery when definining our data source. Then, dbcp will verify the usability of pooled connections by issuing that query (and transparently recreate the connection should it no longer work), prior to returning them to the application.

Check out
http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html
for more details.

暗藏城府 2024-10-08 07:48:10

我目前在我的项目中使用 liquibase(v1.9),当变更集针对空白模式运行时,它总是需要超过 60 秒的时间,这会导致线程被标记为放弃,我对此并不感到兴奋增加 removeAbandonedTimeout 值,但这是我能找到的唯一解决方案来防止此问题;但是,在初始架构填充完成后,这很少会成为问题,因此我将该值设置回 60 秒。

I am currently using liquibase(v1.9) in my project, and when the changeSets run against a blank schema it always takes longer than 60 seconds which results in the thread being marked abandoned I'm not thrilled with increasing the removeAbandonedTimeout value, but this is the only solution I've been able to find to prevent this issue; however, after the initial schema population is complete this is seldom a problem so I set the value back to 60 seconds.

鹿港小镇 2024-10-08 07:48:10

我过去曾解决过一个问题,即我们没有正确地将连接返回到池中。因此,当使用连接但未返回时,在超时时进行数据库调用将引发异常。

我们能够通过调用数据库来重现该问题,等待 8 小时(postgres 的默认超时)并尝试再次调用数据库。它每次都会抛出相同的异常。我们的解决方案是重新考虑(或者更好的是,添加)连接管理策略。

所以,总而言之,您实际上是通过关闭会话将连接返回到池中吗?

I worked on an issue in the past where we weren't returning connections back to the pool correctly. So, when a connection was used and not returned, making a database call when it was timing out would throw an exception.

We were able to reproduce the issue by making a call to the database, waited 8 hours (postgres' default time out) and tried to make a call to the database again. It throw the same exception every time. Our solution was to rethink (or better yet, add) a connection management strategy.

So, to sum up, are you actually returning your connections to the pool by closing the Session?

尹雨沫 2024-10-08 07:48:10

我得到了上述异常的解决方案。
只需在关闭会话时关闭会话工厂的实例即可。

看下面的代码:

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()。这将解决问题。

I got the solution for the above exception.
Just close the instance of session factory as well while closing the session .

Look at the below Code:

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();
        }
    }
}

just call the method HibernateUtil.closeSession(). This will solve the problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文