【发布时间】:2015-12-07 01:35:07
【问题描述】:
我知道有很多关于废弃连接的话题,但是我无法弄清楚我的情况是什么问题,所以我真的希望得到一些帮助。
我有一个带有 Spring 的 Java 应用程序,它从外部服务获取一些数据,并尝试将其保存到数据库中。
我对 JDBC 池有以下配置
<bean id="dataSource"
class="org.apache.tomcat.jdbc.pool.DataSource"
p:initialSize="2"
p:minIdle="10"
p:maxIdle="50"
p:maxActive="100"
p:maxWait="15000"
p:jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer"
p:removeAbandoned="true"
p:removeAbandonedTimeout="60"
p:logAbandoned="true"
p:testOnBorrow="true"
p:testOnReturn="true"
p:testWhileIdle="true"
p:useEquals="false"
p:fairQueue="false"
p:timeBetweenEvictionRunsMillis="300000"
p:minEvictableIdleTimeMillis="300000"
p:validationInterval="10000"
p:validationQuery="SELECT 1">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
这是一个典型的 Spring env,在我的服务中,我有以下方法
@Autowired
private TransactionalWrapper wrapper;
@Override
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void reconcileAllEvents(Date from, Date to) {
for (Event event : eventService.reconcile(from, to)) {
transactionalWrapper.reconcile(event);
}
}
这就是我在TransactionalWrapper中拥有的内容
@Service
public class TransactionalWrapperImpl implements TransactionalWrapper {
@Autowired
private EventRepository eventRepository;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void reconcile(Event event) {
try {
eventRepository.save(event);
} catch (Exception e) {
LOG.warn("Failed to handle event {}", event, e);
}
}
}
每晚都有一个作业在运行,每次大约有 10K 事件。我检查了reconcileAllEvents() 中没有活动事务,并且在TransactionalWrapperImpl.reconcile() 中为每个event 创建并提交了新事务。
问题是我有时会遇到以下异常
Sep 10, 2015 5:25:57 PM org.apache.tomcat.jdbc.pool.ConnectionPool abandon
WARNING: Connection has been abandoned PooledConnection[org.postgresql.jdbc4.Jdbc4Connection@3eb948ed]:java.lang.Exception
at org.apache.tomcat.jdbc.pool.ConnectionPool.getThreadDump(ConnectionPool.java:1063)
at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:780)
at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:619)
at org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:188)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:128)
at org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider.getConnection(InjectedDataSourceConnectionProvider.java:70)
at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:301)
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:214)
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:157)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:67)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:160)
at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1351)
at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:59)
at org.springframework.orm.jpa.DefaultJpaDialect.beginTransaction(DefaultJpaDialect.java:67)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:110)
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:380)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:420)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:257)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
在这个之后还有另一个
10 Sep 2015 17:25:57,591 WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 0, SQLState: 08006
10 Sep 2015 17:25:57,592 ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - An I/O error occurred while sending to the backend.
javax.persistence.PersistenceException: org.hibernate.exception.JDBCConnectionException: could not extract ResultSet
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310)
at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:316)
at com.mysema.query.jpa.impl.AbstractJPAQuery.getSingleResult(AbstractJPAQuery.java:219)
at com.mysema.query.jpa.impl.AbstractJPAQuery.uniqueResult(AbstractJPAQuery.java:295)
at com.mysema.query.jpa.impl.AbstractJPAQuery.uniqueResult(AbstractJPAQuery.java:281)
at com.mysema.query.support.ProjectableQuery.singleResult(ProjectableQuery.java:75)
我检查了几次配置,没有发现任何错误或需要批准的内容,并且一直在崩溃,并且没有保存事件。请注意,异常后它会继续以正常方式保存其余事件。
您知道配置中有什么问题,以及如何处理该问题吗?
【问题讨论】:
-
您的
eventService.reconcile是什么样的。看起来处理时间太长,连接被认为是空闲/放弃。 -
eventService.reconcile(from, to)没有与数据库的任何迭代......它只是通过 API 与外部提供者协调事件的状态......所以我认为根本不应该有任何连接,或者? -
那为什么还要麻烦
@Transactional呢。从数据库中检索对象时发生异常。您显示的代码没有这样做,因此必须有一些东西对数据库进行查询。 -
另一件事是你不应该捕获异常,因为这会破坏正确的 tx 管理。
标签: java spring hibernate postgresql jdbc