if_return_1 2026-01-22 09:38 采纳率: 10%
浏览 4

数据库连接空闲超时问题JAVA

最近程序好长一段时间每隔几天就会包以下错误,导致数据库链接不可能用,一查询数据库就报以下错误,严重影响业务,目前遇到了只能重启,有没有知道怎么解决DE




```,连接池如下:有把连接池调大过还是不行,有没有可能是连接泄漏没及时关闭,但是排查并未发现异常点
<bean id="dataSource"
        class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName">
            <value></value>
        </property>
        <property name="url">
            <value></value>
        </property>
        <property name="username">
            <value></value>
        </property>
        <property name="password">
            <value></value>
        </property>
        <!-- 连接池初始化创建连接数量 -->
        <property name="initialSize" value="20" />
        <!-- 最大空闲连接数量 -->
        <property name="maxIdle" value="45" />
        <!-- 最小空闲连接数量 -->
        <property name="minIdle" value="15" />
        <!-- 最大连接数量 -->
        <property name="maxActive" value="150" />
        <!-- 连接超时是否打印? -->
        <property name="logAbandoned" value="true" />
        <!-- 是否自动回收超时连接? -->
        <property name="removeAbandoned" value="true" />
        <!-- 泄露超时时间是多少?(以秒为单位) -->
        <property name="removeAbandonedTimeout" value="60" />
        <!-- 超时等待时间以毫秒为单位  1000等于60秒 -->
        <property name="maxWait" value="30000" />
        <!-- 在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位 -->
        <property name="timeBetweenEvictionRunsMillis" value="30000" />
        <!-- 在每次空闲连接回收器线程(如果有)运行时检查的连接数量 -->
        <property name="numTestsPerEvictionRun" value="10" />
        <!-- 1000 * 60 * 30  连接在池中保持空闲而不被空闲连接回收器线程 -->
        <property name="minEvictableIdleTimeMillis" value="10000" />
        <property name="validationQuery" value="SELECT 1" />
        <property name="testOnBorrow" value="true"/>
    </bean>
数据库链接URL参数:useUnicode=true&characterEncoding=UTF-8&useOldAliasMetadataBehavior=true&useAffectedRows=false&zeroDateTimeBehavior=convertToNull&useSSL=false

2026-01-21 20:28:13,064 [DubboServerHandler-*******:*****-thread-200] WARN  org.hibernate.util.JDBCExceptionReporter (JDBCExceptionReporter.java:77) - SQL Error: 0, SQLS
tate: 08003
2026-01-21 20:28:13,064 [DubboServerHandler-*******:*****-thread-200] ERROR org.hibernate.util.JDBCExceptionReporter (JDBCExceptionReporter.java:78) - No operations allo
wed after connection closed.
org.springframework.dao.DataAccessResourceFailureException: could not execute query; nested exception is org.hibernate.exception.JDBCConnectionException: could not execute 
query
        at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:627)
        at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
        at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:424)
        at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
        at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:921)
        at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:917)
        at com.isoftstone.fwk.dao.BaseDao.find(Unknown Source)
        at com.**********************.java:1263)
        at com.***********************.java:5323)
        at com.alibaba.dubbo.common.bytecode.Wrapper7.invokeMethod(Wrapper7.java)
        at com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:46)
        at com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:72)
        at com.alibaba.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:53)
        at com.alibaba.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:64)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:65)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:42)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:78)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:60)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:112)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:38)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:38)
        at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
        at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:108)
        at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:84)
        at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:170)
        at com.alibaba.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:52)
        at com.alibaba.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:82)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
Caused by: org.hibernate.exception.JDBCConnectionException: could not execute query
        at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:74)
        at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
        at org.hibernate.loader.Loader.doList(Loader.java:2216)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104)
        at org.hibernate.loader.Loader.list(Loader.java:2099)
        at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:378)
        at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:338)
        at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:172)
        at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1121)
        at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
        at org.springframework.orm.hibernate3.HibernateTemplate$30.doInHibernate(HibernateTemplate.java:930)
        at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:419)
        ... 34 more
Caused by: java.sql.SQLNonTransientConnectionException: No operations allowed after connection closed.
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110)
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89)
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63)
        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:73)
        at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:73)
        at com.mysql.cj.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:1657)
        at com.mysql.cj.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:1573)
        at org.apache.commons.dbcp.DelegatingConnection.prepareStatement(DelegatingConnection.java:281)
        at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.prepareStatement(PoolingDataSource.java:313)
        at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:505)
        at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:423)
        at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:139)
        at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1547)
        at org.hibernate.loader.Loader.doQuery(Loader.java:673)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
        at org.hibernate.loader.Loader.doList(Loader.java:2213)
        ... 43 more
Caused by: com.mysql.cj.exceptions.ConnectionIsClosedException: No operations allowed after connection closed.
        at sun.reflect.GeneratedConstructorAccessor62.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61)
        at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105)
        at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:151)
        at com.mysql.cj.NativeSession.checkClosed(NativeSession.java:1209)
        at com.mysql.cj.jdbc.ConnectionImpl.checkClosed(ConnectionImpl.java:567)
        at com.mysql.cj.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:1588)
        ... 53 more
        ... 53 more
Caused by: com.mysql.cj.exceptions.CJCommunicationsException: The last packet successfully received from the server was 5,094,382 milliseconds ago.  The last packet sent su
ccessfully to the server was 5,094,383 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing co
nnection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=t
rue' to avoid this problem.
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61)
        at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105)
        at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:151)
        at com.mysql.cj.exceptions.ExceptionFactory.createCommunicationsException(ExceptionFactory.java:167)
        at com.mysql.cj.protocol.a.NativeProtocol.readMessage(NativeProtocol.java:541)
        at com.mysql.cj.protocol.a.NativeProtocol.checkErrorMessage(NativeProtocol.java:711)
        at com.mysql.cj.protocol.a.NativeProtocol.sendCommand(NativeProtocol.java:650)
        at com.mysql.cj.protocol.a.NativeProtocol.sendQueryPacket(NativeProtocol.java:949)
        at com.mysql.cj.protocol.a.NativeProtocol.sendQueryString(NativeProtocol.java:895)
        at com.mysql.cj.NativeSession.execSQL(NativeSession.java:1111)
        at com.mysql.cj.jdbc.StatementImpl.executeQuery(StatementImpl.java:1168)
        at com.mysql.cj.jdbc.DatabaseMetaData.getUserName(DatabaseMetaData.java:4079)
        at org.apache.commons.dbcp.DelegatingConnection.toString(DelegatingConnection.java:123)
        at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.toString(PoolingDataSource.java:355)
        at sun.reflect.GeneratedMethodAccessor374.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.hibernate.jdbc.BorrowedConnectionProxy.invoke(BorrowedConnectionProxy.java:50)
        at com.sun.proxy.$Proxy9.toString(Unknown Source)
        at java.lang.String.valueOf(String.java:2994)
        at java.lang.StringBuilder.append(StringBuilder.java:131)
        at com.isoftstone.fwk.dao.BaseDao.getCurrentConnection(Unknown Source)
        at com.isoftstone.fwk.dao.BaseDao.queryNativeSQL(Unknown Source)
        at ****************************************************************:1779)
        at ****************************************************************.java:7192)
        ... 28 more
Caused by: java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.
        at com.mysql.cj.protocol.FullReadInputStream.readFully(FullReadInputStream.java:67)
        at com.mysql.cj.protocol.a.SimplePacketReader.readHeader(SimplePacketReader.java:63)
        at com.mysql.cj.protocol.a.SimplePacketReader.readHeader(SimplePacketReader.java:45)
        at com.mysql.cj.protocol.a.TimeTrackingPacketReader.readHeader(TimeTrackingPacketReader.java:52)
        at com.mysql.cj.protocol.a.TimeTrackingPacketReader.readHeader(TimeTrackingPacketReader.java:41)
        at com.mysql.cj.protocol.a.MultiPacketReader.readHeader(MultiPacketReader.java:54)
        at com.mysql.cj.protocol.a.MultiPacketReader.readHeader(MultiPacketReader.java:44)
        at com.mysql.cj.protocol.a.NativeProtocol.readMessage(NativeProtocol.java:535)
        ... 48 more
  • 写回答

3条回答 默认 最新

  • 檀越@新空间 2026-01-22 09:39
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    你提到的问题是关于 数据库连接空闲超时 导致的 "No operations allowed after connection closed" 错误,这通常与 连接池配置不当、连接泄漏或数据库服务器端的连接超时设置不匹配 有关。以下是你需要关注的关键点和解决方案。


    问题核心分析

    1. 连接池配置问题

    你当前使用的 BasicDataSource 是 Apache DBCP 的一个实现,它虽然功能全面,但在高并发或长时间运行的系统中容易出现连接泄漏、连接失效等问题。

    2. 数据库服务器的连接超时设置

    MySQL 等数据库默认有 wait_timeoutinteractive_timeout 参数,如果连接在该时间内没有活动,就会被服务器主动断开。而你的连接池可能没有及时检测到这些断开的连接,导致程序尝试使用已经失效的连接。

    3. 连接泄漏未被发现

    虽然你排查了代码,但有可能某些地方未正确关闭连接(如异常处理中未关闭),或者连接池未能自动回收已失效的连接。


    🔧 解决方案:优化连接池配置并排查连接泄漏

    第一步:优化连接池配置

    修改后的连接池配置(推荐使用 HikariCP 或 Druid):

    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/dbname?useUnicode=true&characterEncoding=UTF-8&useSSL=false"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
        
        <!-- 连接池参数 -->
        <property name="maximumPoolSize" value="150"/>
        <property name="minimumIdle" value="15"/>
        <property name="idleTimeout" value="60000"/> <!-- 空闲连接超时时间(毫秒) -->
        <property name="connectionTimeout" value="30000"/> <!-- 获取连接最大等待时间(毫秒) -->
        <property name="validationTimeout" value="5000"/> <!-- 验证连接是否有效的超时时间 -->
        <property name="leakDetectionThreshold" value="60000"/> <!-- 泄漏检测阈值(毫秒) -->
    
        <!-- 自动验证连接有效性 -->
        <property name="testWhileIdle" value="true"/>
        <property name="validationQuery" value="SELECT 1"/>
    </bean>
    

    注意: 如果你坚持使用 DBCP,请确保 testOnBorrowtestWhileIdlevalidationQuery 等配置正确,并且开启 logAbandonedremoveAbandoned


    第二步:检查并修复连接泄漏

    检查代码中是否有如下问题:

    • 使用完 Connection 后未调用 close()
    • 在 try-with-resources 中未正确释放资源。
    • 异常处理中未关闭连接。

    示例修复代码(Java):

    try (Connection conn = dataSource.getConnection();
         PreparedStatement stmt = conn.prepareStatement("SELECT * FROM table")) {
        // 执行查询逻辑
    } catch (SQLException e) {
        // 处理异常
    }
    

    第三步:调整数据库服务器的超时设置

    如果你无法修改应用层配置,可以考虑调整数据库的连接超时时间,以匹配应用的连接池配置。

    MySQL 配置示例(在 my.cnf 中):

    [mysqld]
    wait_timeout = 28800  # 8小时
    interactive_timeout = 28800
    

    注意: 调整后需重启 MySQL 服务生效。


    第四步:监控连接池状态

    你可以通过日志或监控工具(如 JMX、Prometheus + Grafana)来观察连接池的使用情况,包括:

    • 当前活跃连接数
    • 空闲连接数
    • 连接泄漏数量
    • 连接超时次数

    📌 总结:关键点

    1. 优先更换为 HikariCP 或 Druid 连接池,性能更好、更稳定。
    2. 确保连接池配置合理,尤其是 testWhileIdlevalidationQueryidleTimeout 等参数。
    3. 检查代码中的连接泄漏问题,确保所有资源都正确关闭。
    4. 调整数据库的 wait_timeout,使其与应用的连接池配置相匹配。
    5. 定期监控连接池状态,及时发现问题。

    🧠 建议:使用现代连接池替代 DBCP

    由于 DBCP 已经逐渐被弃用,建议使用 HikariCPDruid,它们对连接泄漏和超时的处理更加智能。


    如有需要,我可以提供完整的 HikariCP 或 Druid 的配置示例,也可以帮助你进行连接泄漏的代码审查。

    评论

报告相同问题?

问题事件

  • 创建了问题 1月22日