SQLRecoverableException: 关闭的连接 尝试解决办法

错误效果:

[11:31:31] [ERROR] - com.alibaba.druid.util.JdbcUtils.close(JdbcUtils.java:109) - close statement error
java.sql.SQLRecoverableException: 关闭的连接
	at oracle.jdbc.driver.PhysicalConnection.needLine(PhysicalConnection.java:3525) ~[ojdbc8-19.3.0.0.jar!/:19.3.0.0.0]
	at oracle.jdbc.driver.OracleStatement.closeOrCache(OracleStatement.java:1478) ~[ojdbc8-19.3.0.0.jar!/:19.3.0.0.0]
	at oracle.jdbc.driver.OracleStatement.close(OracleStatement.java:1461) ~[ojdbc8-19.3.0.0.jar!/:19.3.0.0.0]
	at oracle.jdbc.driver.OracleStatementWrapper.close(OracleStatementWrapper.java:122) ~[ojdbc8-19.3.0.0.jar!/:19.3.0.0.0]
	at com.alibaba.druid.util.JdbcUtils.close(JdbcUtils.java:98) ~[druid-1.2.8.jar!/:1.2.8]
	at com.alibaba.druid.pool.vendor.OracleValidConnectionChecker.isValidConnection(OracleValidConnectionChecker.java:92) ~[druid-1.2.8.jar!/:1.2.8]
	at com.alibaba.druid.pool.DruidAbstractDataSource.testConnectionInternal(DruidAbstractDataSource.java:1476) ~[druid-1.2.8.jar!/:1.2.8]
	at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:1482) ~[druid-1.2.8.jar!/:1.2.8]
	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1407) ~[druid-1.2.8.jar!/:1.2.8]

出现的原因:

当数据库连接池中的连接被创建而长时间不使用的情况下,该连接会自动回收并失效,但客户端并不知道,在进行数据库操作时仍然使用的是无效的数据库连接,这样,就导致客户端程序报“ java.sql.SQLException: Io 异常: Connection reset” 或“java.sql.SQLException 关闭的连接”异常。

1:先检查druid的版本,使用1.2.*以后的版本,1.1.*版本有问题,相关文章有说明


    com.alibaba
    druid-spring-boot-starter
    1.2.11

2:优化druid配置

spring:
  application:
    name: project
  datasource:
    druid:
      db1:
        driver-class-name: oracle.jdbc.OracleDriver
        username: abcd
        password: 123456
        url: jdbc:oracle:thin:@//1.2.1.1:1521/orads
        validation-query: SELECT 1 FROM DUAL
        initial-size: 30
        min-idle: 30
        max-active: 400
        max-wait: 8000
        time-between-eviction-runs-millis: 60000
        min-evictable-idle-time-millis: 300000
        num-tests-per-eviction-run: 3
        test-while-idle: true
        test-on-borrow: true
        test-on-return: false
        keep-alive: true
        pool-prepared-statements: true
        max-pool-prepared-statement-per-connection-size: 20
        filters: stat
        filter:
          stat:
            slow-sql-millis: 500
        use-global-data-source-stat: true
        connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
      qywx:
        driver-class-name: com.mysql.cj.jdbc.Driver 
        username: xyz
        password: 123456
        url: jdbc:mysql://1.2.3.4:3306/qyweixing?autoReconnect=true&failOverReadOnly=false&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai
        validation-query: SELECT 1
        initial-size: 30
        min-idle: 30
        max-active: 400
        max-wait: 8000
        time-between-eviction-runs-millis: 60000
        min-evictable-idle-time-millis: 300000
        num-tests-per-eviction-run: 3
        test-while-idle: true
        test-on-borrow: true
        test-on-return: false
        keep-alive: true
        pool-prepared-statements: true
        max-pool-prepared-statement-per-connection-size: 20
        filters: stat
        filter:
          stat:
            slow-sql-millis: 500
        use-global-data-source-stat: true
        connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

解决办法中 druid 配置参数说明:

属性 默认值 备注
testOnBorrow false 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
testOnBorrow false 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
testWhileIdle true 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
timeBetweenEvictionRunsMillis 单位毫秒 有两个含义:1) Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明
validationQuery 用来测试连接是否可用的SQL语句
minEvictableIdleTimeMillis 1000L * 60L * 30L 连接空闲时间大于该值并且池中空闲连接大于minIdle则关闭该连接 。默认30分钟
keepAlive false 保持连接的有效性,也就是跟数据库续租,只有空闲时间大于keepAliveBetweenTimeMillis并且小于minEvictableIdleTimeMillis该参数才会有用

连接池配置文件中以上参数都有进行配置,但是程序还是有报错;可以根据报错日志,错定位所使用的连接池,然后定位对应连接池创建的代码,看看是否是创建连接池的时候缺了以上对应的参数配置。

关键点:


为什么 validation-query 需要放在每个数据源下?

Druid 可以管理多个数据源,每个数据源可能连接到不同的数据库,因此每个数据源的配置可能不同。比如:

如果你放在全局 druid 下,它可能只会对默认数据源有效,而其他数据源就会忽略掉这个配置。

总结:

这样就能确保每个数据源在获取连接时,都能根据相应的数据库类型进行有效性验证。

希望这次解释清楚了!如果有更多问题,随时告诉我。

  • validation-query:需要放在每个数据源(如 druid.masterdruid.order)的配置下。每个数据源可能有不同的验证需求。

  • test-on-borrowtest-while-idle:建议这两个选项都启用,以确保在借用连接和空闲时都进行有效性验证。

  • Oracle 数据库:通常使用 SELECT 1 FROM DUAL 来验证连接。

  • MySQL 数据库:通常使用 SELECT 1 来验证连接。

  • 在你的场景下,配置应该放在每个数据源的级别下,例如 druid.masterdruid.order 等。

  • validation-query 应该针对每个数据源配置,不是全局配置。

你可能感兴趣的:(java,前端,服务器)