连接关闭后不允许任何操作

Posted

技术标签:

【中文标题】连接关闭后不允许任何操作【英文标题】:No operations allowed after connection closed 【发布时间】:2015-02-16 09:09:51 【问题描述】:

我从 Java 应用程序收到此错误:

com.mchange.v2.c3p0.impl.NewPooledConnection - [c3p0] Another 
error has occurred [     
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: 
No operations allowed after connection closed. ] which will not be 
reported to listeners!

Java 代码:

try 
    sessionFactory.beginTransaction();
    //...
    sessionFactory.commitTransaction();
 catch (Exception e) 
    sessionFactory.rollbackTransaction();
    throw new RuntimeException(e);

会话工厂:

try 
    sessionFactory.beginTransaction();
    ...
    sessionFactory.commitTransaction();
 catch (Exception e) 
    sessionFactory.rollbackTransaction();
    throw new RuntimeException(e);


public Transaction beginTransaction() throws HibernateException 
    try 
        return sessionFactory.getCurrentSession().beginTransaction();
     catch (HibernateException hex) 
        LOG.error(String.format("Unable to start database transaction due to exception: %s.", ExceptionUtils.getRootCauseMessage(hex)));
        throw hex;
    


public void commitTransaction() throws HibernateException 
    LOG.debug("Committing database transaction.");
    try 
        if (sessionFactory.getCurrentSession().getTransaction().isActive()) 
            sessionFactory.getCurrentSession().getTransaction().commit();
         else 
            throw new HibernateException("Transaction is no longer Active.");
        
     catch (HibernateException hex) 
        LOG.error(String.format("Unable to commit due to exception: %s.", ExceptionUtils.getRootCauseMessage(hex)));
        throw hex;
    


public void rollbackTransaction() throws HibernateException 
    LOG.debug("Trying to rollback database transaction after exception.");
    Session session = sessionFactory.getCurrentSession();
    try 
        if (session.getTransaction().isActive()) 
            session.getTransaction().rollback();
         else 
            throw new HibernateException("Transaction is no longer Active.");
        
     catch (HibernateException hex) 
        LOG.error(String.format("Unable to rollback due to exception: %s.", ExceptionUtils.getRootCauseMessage(hex)));
        throw hex;
     finally 
        if (session.isOpen()) 
            session.close();
        
    

休眠和 C3P0 设置:

<prop key="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</prop>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>

<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</prop>
<prop key="hibernate.jdbc.batch_size">20</prop>
<prop key="hibernate.order_inserts">true</prop>
<prop key="hibernate.order_updates">true</prop>
<prop key="hibernate.c3p0.timeout">1800 <!-- seconds --></prop>
<prop key="hibernate.c3p0.min_size">4</prop>
<prop key="hibernate.c3p0.max_size">35</prop>
<prop key="hibernate.c3p0.idle_test_period">240 <!-- seconds --></prop>
<prop key="hibernate.c3p0.acquire_increment">4</prop>
<prop key="hibernate.c3p0.max_statements">0</prop>
<prop key="hibernate.c3p0.preferredTestQuery">SELECT 1</prop>
<prop key="c3p0.testConnectionOnCheckout">true</prop>
<prop key="hibernate.connection.oracle.jdbc.ReadTimeout">60000 <!-- milliseconds --></prop>

不确定连接如何仍在使用中并引发此错误。是什么导致了这个错误?

【问题讨论】:

如果没有看到所有代码,我不能肯定地说,但是您是否在成功提交后关闭会话?我在上面的代码中没有看到。如果没有,您将耗尽您的连接池。 事务提交时会话自动关闭:developer.jboss.org/wiki/…. 【参考方案1】:

这个 Java 方法称为 executeQuery:

your_database_connection.createStatement().executeQuery(your_string_query);

会抛出这个异常:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: 
No operations allowed after connection closed.

如果您在调用后尝试运行它(executeQuery):

your_database_connection.close()

发生了什么

您要么尝试建立与数据库的连接但没有获得连接,要么尝试对它运行失败的查询。或者您的连接遇到问题并关闭,您尝试通过它运行另一个查询。

解决方案

假设您因网络问题或不是您的错而失去连接,然后将尝试查询的代码放在 try/catch 块中,并在出错时等待 10 秒并重新连接到数据库。

【讨论】:

【参考方案2】:

您的 idleConnectionTestPeriod 是 240,它应该小于 db 等待超时值,请参阅 db 配置,检查该值是否大于 240。

【讨论】:

以上是关于连接关闭后不允许任何操作的主要内容,如果未能解决你的问题,请参考以下文章

MySQLNonTransientConnectionException:连接关闭后不允许操作。连接

Docker MySQL在超时后丢弃表:连接关闭后不允许操作

HikariCP - MYSQL 连接关闭后不允许操作。可能考虑使用更短的 maxLifetime 值

java.sql.SQLException:ResultSet关闭后不允许操作[重复]

获取 java.sql.SQLException:ResultSet 关闭后不允许操作

结果集自动关闭并显示错误结果集关闭后不允许操作