基础 - 解决 Hibernate / JDBC 连接池问题
Posted
技术标签:
【中文标题】基础 - 解决 Hibernate / JDBC 连接池问题【英文标题】:Basics - Troubleshooting Hibernate / JDBC Connection Pool Issue 【发布时间】:2011-05-05 16:05:10 【问题描述】:Hibernate 从底层连接池获得的数据库连接的责任是什么。它是否在使用连接之前测试连接是否已关闭?如果是这样,从池中获得另一个连接?
我在下面包含了错误和确认信息。关于我可以从哪里开始解决此问题的任何想法都会非常有帮助。以及有关我们正在使用的 SQL Server 驱动程序设置的任何建议。
来自 Catalina 日志:
2010 年 11 月 4 日 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) 在 org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:681) 在 org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:545) 在 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] WARN 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:连接已经关闭。 在 org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:112) 在 org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:94) 在 org.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor.invoke(AbstractCreateStatementInterceptor.java:71) 在 org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:94) 在 org.apache.tomcat.jdbc.pool.interceptor.ConnectionState.invoke(ConnectionState.java:132) 在 $Proxy38.rollback(未知来源) 在 org.hibernate.transaction.JDBCTransaction.rollbackAndResetAutoCommit(JDBCTransaction.java:217) 在 org.hibernate.transaction.JDBCTransaction.rollback(JDBCTransaction.java:196) 在 org.springframework.orm.hibernate3.HibernateTransactionManager.doRollback(HibernateTransactionManager.java:676) 在 org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:845) 在 org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:822) 在 org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.java:412) 在 org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:111) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 在 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"/>`
【问题讨论】:
【参考方案1】:我有一个类似的问题,通过将 removeAbandonedTimeout 值增加到更高的数字来解决。我们面临的问题是由于查询花费了比上述超时更长的时间。
【讨论】:
你在开玩笑吗?您只是将问题转移到未来更长时间的事件中 刚刚遇到同样的问题。在我的情况下,执行由 Hibernate 创建的 OUTER JOIN(由于具有 EAGERly 加载的“OneToMany”依赖项的实体)结果花费了很多时间(比我的“removeAbandonedTimeout”设置(60)多,并且导致 SQLState : 08S01 错误。看起来 Hibernate 在处理废弃的连接删除时遇到了困难。【参考方案2】:Hibernate 从底层连接池获得的数据库连接的责任是什么。
不多,当Session
关闭时释放它。
它是否会在使用连接之前测试它是否已关闭?如果是这样,从池中获得另一个连接?
不,Hibernate 没有,如果您愿意,检查连接的有效性是连接池的责任。
我在下面包含了错误和确认信息。任何关于我可以从哪里开始解决此问题的想法都会非常有帮助。
您正在运行什么样的进程?长期交易?是否超时? Caused by:
说了什么?关于跟踪:
你能以一种确定的方式重现它吗?有网络问题吗?
以及关于我们正在使用的 SQL Server 驱动程序设置的任何建议。
我在下面添加了有关 Tomcat 和连接池配置的精彩资源。虽然不是特定于 SQL Server。
资源
Configuring jdbc-pool for high-concurrency【讨论】:
原来的链接没了,但是被wayback机器记录下来了:web.archive.org/web/20180521112213/http://www.tomcatexpert.com/…【参考方案3】:我们通常通过使用 dbcp 来解决这个问题,并在定义我们的数据源时提供一个验证查询。然后,dbcp 将通过发出该查询来验证池连接的可用性(并在它不再工作时透明地重新创建连接),然后再将它们返回给应用程序。
退房 http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html 了解更多详情。
【讨论】:
【参考方案4】:我目前在我的项目中使用 liquibase(v1.9)
,当 changeSets 针对空白架构运行时,它总是需要超过 60 秒的时间,这导致线程被标记为废弃,但这是我能够找到的唯一解决此问题的解决方案;但是,在初始模式填充完成后,这很少会成为问题,因此我将值设置回 60 秒。
【讨论】:
【参考方案5】:我过去曾处理过一个问题,即我们没有将连接正确返回到池中。因此,当一个连接被使用但没有返回时,在超时时进行数据库调用会引发异常。
我们能够通过调用数据库来重现该问题,等待 8 小时(postgres 的默认超时)并尝试再次调用数据库。它每次都会抛出相同的异常。我们的解决方案是重新考虑(或者更好的是,添加)连接管理策略。
所以,总而言之,您实际上是通过关闭 Session 将连接返回到池中吗?
【讨论】:
当我尝试一次插入许多记录时,我也遇到了这个问题(上传作业,文件由 1,60,000 条记录组成)。 5分钟后我得到了错误。能够在 5 分钟后抛出错误的所有时间重现多次。有人可以帮我吗?【参考方案6】:我得到了上述异常的解决方案。 在关闭会话的同时也关闭会话工厂的实例。
看下面的代码:
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()。这样就可以解决问题了。
【讨论】:
我不认为这是推荐的:***.com/questions/33236407/…以上是关于基础 - 解决 Hibernate / JDBC 连接池问题的主要内容,如果未能解决你的问题,请参考以下文章