【问题标题】:PostgreSQL throws "Connection has been abandoned" -> "An I/O error occurred while sending to the backend"PostgreSQL 抛出“连接已被放弃”->“发送到后端时发生 I/O 错误”
【发布时间】: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


【解决方案1】:

这通常由 PostgreSQL 在后端断开连接时抛出。

  1. 尝试将驱动程序更新到最新版本:9.4-1202
  2. postgresql.conf 尝试设置:log_statement = 'all',查看所有语句日志数据,以便您更好地了解导致问题的原因。

【讨论】:

  • 我已将驱动程序更改为最新版本,但不幸的是它没有帮助。虽然为 postgre 启用日志是个好主意,但会尝试更深入地挖掘!
  • 所以确实有一个查询导致了这个问题!非常感谢在 postgre 中启用日志的提示。
【解决方案2】:

这很可能是因为您的外部方法正在使用事务传播 NOT_SUPPORTED。此配置将暂停其他打开的事务,并且随着处理大量数据,这些暂停的事务可能会发生超时。

我知道你说这个方法是在没有活动交易的时候执行的,但是你完全确定吗?单一结果错误表明正在执行一个 select 语句。

您可以尝试另一种适合您要求的传播配置,看看它是否有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 2020-07-22
    • 1970-01-01
    • 2020-08-22
    • 2020-03-15
    • 1970-01-01
    相关资源
    最近更新 更多