spring boot访问数据Connection is not available【原创】

本文解决了一个在SpringBoot项目中遇到的问题,即部分数据库读取操作因连接超时而失败。通过调整数据库连接池配置,从HikariPool更换为DBCP2,并详细配置参数,成功解决了连接失效的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在运行自己的项目发现一个问题,有些读取数据库能正常访问,有些读取数据库拒绝连接,发现把spring事务取消掉,就能正常读取数据,提示如下错误消息:

HikariPool-1 - Connection is not available, request timed out after 30096ms

经过几天的不懈努力,终于解决了这个问题。

因为我使用的是如下代码来连接数据库:

@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;

导致事务读取数据后并且释放连接,而这些连接依然存在数据库连接池中,导致再次请求数据的时候,因为连接已经失效或者关闭,就会提示上面的错误。

百度、google最后找到解决办法,这里先是说明一下,因为使用HikariPool连接池一直没有解决问题,我换成了DBCP2连接池,问题原因也是一样,解决方式大致一样,只不过是配置项名称不同吧了:

spring.datasource:
  type: org.apache.commons.dbcp2.BasicDataSource
  dbcp2:
      default-auto-commit: true
      initial-size: 30
      max-total: 120
      max-idle: 120
      min-idle: 30
      max-wait-millis: 10
      validation-query: 'SELECT 1'
      validation-query-timeout: 3
      test-on-borrow: true
      test-while-idle: true
      time-between-eviction-runs-millis: 10000
      num-tests-per-eviction-run: 10
      min-evictable-idle-time-millis: 120000
      remove-abandoned-on-borrow: true
      remove-abandoned-timeout: 120
      pool-prepared-statements: true

现在将配置项的详细配置说明贴在如下:

注意:文章到这里还没有完,由于篇幅限制,完整内容请到hongfu951博客上查看

完整内容URL地址:spring boot访问数据Connection is not available【原创】

欢迎访问:www.hongfu951.com博客,查看更多文章

<think>我们面对的是数据库连接超时问题,具体报错是“Connection is not available, request timed out after 30000ms”。根据引用内容,我们可以从多个角度排查。 首先,根据引用[1],我们知道Spring Boot默认的max-lifetime是30分钟(1800000毫秒),但报错频率高于这个间隔,因此怀疑数据库端的超时设置。需要检查数据库的超时设置,比如数据库的wait_timeout(MySQL)或类似参数。 其次,引用[2]提供了两个主要原因: 1. 连接泄漏:从连接池借用连接后没有关闭。 2. 复杂操作导致连接占用时间过长,耗尽连接池。 针对连接泄漏,我们可以通过配置连接池的泄漏检测参数来定位。对于复杂操作,建议将方法标记为@Transactional,确保在一个事务中执行,或者增加连接池的最大连接数。 另外,引用[3]提到了不同数据库驱动程序的超时参数设置,例如MySQL的connectTimeout和socketTimeout,这些参数可以通过JDBC URL设置。 因此,解决方案可以按以下步骤进行: 1. **检查数据库服务端的超时设置**:比如MySQL的wait_timeout,如果这个值小于连接池中连接的最大存活时间(maxLifetime),则可能导致数据库主动关闭连接,而连接池还在使用。需要确保maxLifetime小于数据库的wait_timeout(一般建议小于几秒)。 2. **检查连接泄漏**: - 配置HikariCP的leakDetectionThreshold参数,当连接借用超过一定时间未归还时会记录警告,帮助定位泄漏点。 - 示例配置:`spring.datasource.hikari.leak-detection-threshold=60000`(单位毫秒,表示如果连接被借用超过60秒未归还则记录泄漏) 3. **调整连接池参数**: - 增加最大连接数:`spring.datasource.hikari.maximum-pool-size`(根据实际情况调整,比如从默认的10调整为20或更高) - 调整连接超时时间:`spring.datasource.hikari.connection-timeout`(默认30000毫秒,可以适当增加,但不要过长) - 设置最大存活时间(maxLifetime)小于数据库的wait_timeout(例如,如果数据库wait_timeout是300秒,则maxLifetime设置为280秒,即280000毫秒) 4. **事务管理**:确保在复杂业务方法上使用@Transactional,避免多个独立操作占用多个连接。同时,检查代码中是否有未关闭的资源(如ResultSet、Statement、Connection等),确保在finally块中关闭或使用try-with-resources。 5. **数据库驱动超时设置**:在JDBC URL中设置连接超时和socket超时,例如MySQL: ``` jdbc:mysql://localhost:3306/db?connectTimeout=60000&socketTimeout=60000 ``` 6. **监控连接池状态**:可以通过JMX或Spring Boot Actuator的`/actuator/hikaricp`端点监控连接池状态,查看活跃连接数、空闲连接数等。 具体配置示例(application.properties): ```properties # 连接池配置 spring.datasource.hikari.connection-timeout=60000 # 连接超时时间(毫秒) spring.datasource.hikari.maximum-pool-size=20 # 最大连接数 spring.datasource.hikari.minimum-idle=10 # 最小空闲连接 spring.datasource.hikari.idle-timeout=600000 # 空闲连接超时时间(毫秒) spring.datasource.hikari.max-lifetime=280000 # 最大存活时间(毫秒),小于数据库wait_timeout spring.datasource.hikari.leak-detection-threshold=60000 # 泄漏检测阈值(毫秒) # 对于MySQL,还可以在URL中设置超时参数 spring.datasource.url=jdbc:mysql://localhost:3306/mydb?connectTimeout=60000&socketTimeout=60000 ``` 如果以上调整后问题仍然存在,需要进一步检查代码中是否有连接泄漏(如未关闭的连接)或者数据库性能问题(如慢查询导致连接长时间占用)。 §§相关问题§§ 1. 如何监控HikariCP连接池的运行状态? 2. 除了HikariCP,还有哪些常见的Java数据库连接池? 3. 如何配置Spring Boot使用不同的数据库连接池?</think>### 数据库连接超时问题排查与解决方案 #### 问题分析 当出现 `Connection is not available, request timed out after 30000ms` 错误时,通常表示数据库连接池无法在指定时间(30秒)内提供可用连接。根据引用内容,主要原因包括: 1. **连接泄漏**:从连接池借用的连接未正确关闭[^2] 2. **连接池配置不当**:超时参数、最大连接数等配置不合理[^1][^2] 3. **事务管理问题**:复杂操作未封装事务导致连接占用时间过长[^2] 4. **数据库服务端超时**:数据库主动断开空闲连接[^1][^3] --- ### 解决方案步骤 #### 1. 检查连接泄漏 ```java // Spring Boot配置示例(application.properties) spring.datasource.hikari.leak-detection-threshold=60000 // 60秒泄漏检测 spring.datasource.hikari.max-lifetime=1800000 // 30分钟(需小于数据库超时) ``` - **原理**:设置泄漏检测阈值,自动回收未关闭连接 - **操作**:检查代码中所有`Connection`、`Statement`、`ResultSet`是否在`finally`块关闭 #### 2. 优化连接池参数 ```java // 推荐配置(单位:毫秒) spring.datasource.hikari.connection-timeout=60000 // 连接等待超时 spring.datasource.hikari.validation-timeout=3000 // 连接验证超时 spring.datasource.hikari.idle-timeout=600000 // 空闲连接超时 spring.datasource.hikari.maximum-pool-size=20 // 最大连接数 ``` - **关键点**:`max-lifetime` 必须小于数据库的 `wait_timeout`(MySQL默认28800秒)[^1] #### 3. 配置数据库驱动超时 ```sql -- MySQL JDBC URL示例 jdbc:mysql://host:port/db?connectTimeout=60000&socketTimeout=60000 ``` - **Oracle**:需通过`OracleDataSource.setConnectionProperties()`设置 - **SQL Server**:`jdbc:jtds:sqlserver://...;loginTimeout=60;socketTimeout=60`[^3] #### 4. 事务优化 ```java @Transactional // 添加事务注解确保原子操作 public void complexOperation() { // 数据库操作 } ``` - **作用**:避免多个独立操作占用多个连接[^2] - **注意**:事务范围不宜过大 #### 5. 数据库服务端检查 ```sql -- MySQL超时设置检查 SHOW VARIABLES LIKE 'wait_timeout'; -- 默认28800秒(8小时) ``` - **调整建议**:保持`wait_timeout > max-lifetime + 60秒`缓冲 --- ### 总结流程图 ```mermaid graph TD A[报错Connection timed out] --> B{检查连接泄漏} B -->|是| C[添加泄漏检测配置] B -->|否| D{检查连接池配置} D -->|不合理| E[调整超时参数/最大连接数] D -->|合理| F{检查事务管理} F -->|未封装| G[添加@Transactional] F -->|已封装| H{检查数据库超时设置} H -->|wait_timeout过小| I[调整数据库配置] H -->|正常| J[检查网络/数据库负载] ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值