调用第三方接口过长导致数据库连接超时( Communications link failure during rollback(). Transaction resolution unknown.)

业务逻辑是:推送按钮-处理推送逻辑-往第三方系统推送文件(大文件几十分钟)-推送完成-记录推送状态-操作完成

在推送完成往数据库写入数据的时候抛出如下异常:

com.mysql.cj.jdbc.exceptions.CommunicationsException: The last packet successfully received from the server was 5,401,659 milliseconds ago. The last packet sent successfully to the server was 5,401,672 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.

根据异常内容可知是数据库连接超时导致的,建议用'autoReconnect=true' ,但是数据库连接配置加了这个也没用,后面又想到用连接池加入如下配置:

druid:
  maxWait: 60000
  timeBetweenEvictionRunsMillis: 60000
  minEvictableIdleTimeMillis: 300000
  validationQuery: SELECT 1
  testWhileIdle: true
  testOnBorrow: false
  testOnReturn: false
  
<think>嗯,用户遇到了Spring框架中JDBC回滚时出现通信链接失败的问题,具体异常是DataAccessResourceFailureException,并且提到回滚时出现通信链接故障。我需要根据提供的引用资料和系统级指令来整理解决方案。 首先,我需要理解这个问题的可能原因。根据引用[5],MySQL的wait_timeout设置可能导致连接超时,特别是在长时间空闲的事务中。如果事务处理时间超过wait_timeout,连接会被服务器关闭,回滚时就会失败。此外,数据库连接池的配置可能不合适,比如最大存活时间超过数据库超时设置,或者连接泄漏未关闭,导致连接被占用过久。 接下来,解决步骤应该包括检查数据库配置,比如调整wait_timeout和interactive_timeout,确保足够长。然后检查连接池配置,如HikariCP的maxLifetime应小于数据库超时时间,防止连接被提前关闭。另外,需要优化事务范围,避免长时间持有连接,使用重试机制,以及实现连接泄漏检测。 异常处理方面,引用[1]提到捕获DataAccessResourceFailureException并处理,比如记录日志、通知管理员或进行重试。同时,引用[5]提到调整MySQL的wait_timeout参数,这也是一个关键点。 用户可能需要具体的配置示例,比如如何修改MySQL的my.cnf文件,或者如何在Spring Boot中配置HikariCP的参数。此外,事务管理的最佳实践,比如使用@Transactional注解合理设置超时时间,也是重要的。 还要注意,在回滚过程中出现通信失败,可能需要确保应用程序能够处理这种异常,避免数据不一致。可能需要手动处理事务状态,或者在应用层进行补偿操作。 最后,生成相关问题时要围绕这个主题,比如如何调整超时时间、连接池配置、事务管理优化等,帮助用户深入理解问题。</think>### 逐步解决方案:Spring JDBC回滚通信链接失败问题 #### 1. **问题定位与原因分析** 当Spring框架执行JDBC事务回滚时出现`DataAccessResourceFailureException`并伴随**Communications link failure**,通常由以下原因导致: - **数据库连接超时**:MySQL默认的`wait_timeout`(默认28800秒)或`interactive_timeout`设置过短,导致空闲事务连接被强制关闭[^5]。 - **连接池配置不当**:连接池(如HikariCP)的`maxLifetime`参数大于数据库超时时间,造成连接在事务中突然失效。 - **事务范围过大**:长时间未提交的事务占用连接,触发数据库主动断开。 - **网络不稳定**:数据库与应用服务器之间网络波动导致通信中断。 #### 2. **具体解决步骤** ##### 2.1 **调整MySQL超时配置** 修改MySQL配置文件`my.cnf`或通过SQL语句动态调整: ```sql SET GLOBAL wait_timeout = 300; -- 单位:秒(建议设置为应用最大事务时间的1.5倍) SET GLOBAL interactive_timeout = 300; ``` 并在配置文件中永久生效: ```ini [mysqld] wait_timeout=300 interactive_timeout=300 ``` 重启MySQL服务后验证配置。 ##### 2.2 **优化连接池参数** 以HikariCP为例,在Spring Boot的`application.yml`中配置: ```yaml spring: datasource: hikari: max-lifetime: 250000 # 必须小于数据库的wait_timeout connection-timeout: 30000 leak-detection-threshold: 10000 # 检测未关闭连接(毫秒) ``` 确保`max-lifetime < wait_timeout - 10秒`以预留缓冲时间。 ##### 2.3 **事务管理与异常处理** 缩小事务范围并添加重试机制: ```java @Transactional(timeout = 60) // 设置事务超时时间为60秒 public void transactionalMethod() { try { // 业务操作 } catch (DataAccessResourceFailureException e) { // 记录异常并触发重试逻辑 handleRetry(e); } } private void handleRetry(DataAccessResourceFailureException e) { if (isNetworkRelated(e.getCause())) { retryTemplate.execute(ctx -> { // 重试数据库操作 return null; }); } } ``` ##### 2.4 **实现连接泄漏检测** 通过JDBC驱动参数强制验证连接有效性: ```yaml spring: datasource: url: jdbc:mysql://localhost:3306/db?testOnBorrow=true&validationQuery=SELECT 1 ``` #### 3. **关键代码示例** ```java // 事务管理器配置 @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { DataSourceTransactionManager tm = new DataSourceTransactionManager(dataSource); tm.setDefaultTimeout(60); // 全局事务超时时间 return tm; } // 异常处理示例 try { jdbcTemplate.execute("UPDATE accounts SET balance = balance - 100 WHERE user_id = 1"); } catch (DataAccessResourceFailureException e) { if (e.contains(CommunicationsException.class)) { logger.error("网络通信失败,尝试重新建立连接: {}", e.getMessage()); resetConnectionPool(); // 重置连接池 } throw new TransactionSystemException("事务回滚失败,需人工干预", e); } ``` #### 4. **验证与监控** - **日志监控**:通过Spring AOP记录事务执行时间: ```java @Aspect @Component public class TransactionMonitor { @Around("@annotation(org.springframework.transaction.annotation.Transactional)") public Object logTransactionTime(ProceedingJoinPoint joinPoint) throws Throwable { long start = System.currentTimeMillis(); Object result = joinPoint.proceed(); long duration = System.currentTimeMillis() - start; logger.info("事务执行时间: {}ms", duration); return result; } } ``` - **数据库状态检查**:定期执行`SHOW PROCESSLIST`观察活跃连接状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值