sqlrecoverableexception不是自动修复异常,而是提示可主动重试的受检异常;需开发者显式实现重连、重试逻辑,结合连接池健康检查与幂等设计,避免盲目重试导致数据不一致。

SQLRecoverableException 表示数据库连接或操作因临时性问题(如网络抖动、数据库短暂不可用、连接池耗尽、事务超时等)失败,但**不需修改代码逻辑即可重试**。它本身不是自动重试的触发器,而是你决定是否重试的重要信号。
识别哪些场景适合重试
不是所有 SQLRecoverableException 都该重试。重点看异常原因和当前操作性质:
-
可重试:连接超时(
IO Error: The Network Adapter could not establish the connection)、Socket读写超时、Oracle 的 ORA-03113/ORA-03114、MySQL 的Communications link failure - 不可重试:已提交事务中的部分失败(如批量插入中途断连)、DDL 操作失败、违反约束(此时重试只会重复报错)、连接已明确关闭且无法重建
- 需谨慎:涉及幂等性判断的操作(如 INSERT 不带唯一约束),重试可能造成重复数据
手动实现简单重试逻辑
Spring 或 JDBC 本身不自动重试,需自行封装。推荐使用指数退避 + 最大重试次数:
- 捕获
SQLRecoverableException(注意:它继承自SQLException,需向上转型判断) - 检查
getCause()或getSQLState()/getErrorCode()做更细粒度判断(如 Oracle 错误码 17002、MySQL 错误码 0 或 1045) - 每次重试前 sleep(如 100ms → 200ms → 400ms),避免雪崩
- 重试后重新获取连接(不能复用原 Connection,它大概率已失效)
借助框架简化重试
Spring Retry 是最常用方案:
- 添加依赖:
spring-retry+spring-aop - 启用重试:
@EnableRetry(配置类)或@SpringBootApplication类上加 - 在 service 方法上标注:
@Retryable(value = SQLRecoverableException.class, maxAttempts = 3, backoff = @Backoff(delay = 100, multiplier = 2)) - 补充兜底:
@Recover方法处理最终失败情况(如发告警、写日志、降级返回)
连接池层面的“自动恢复”辅助
重试效果依赖底层连接是否真正可用。建议配合连接池配置提升鲁棒性:
- HikariCP 设置
connection-test-query=SELECT 1(新版用connection-test-query已废弃,改用connection-checker-class-name或validation-timeout) - 开启
test-on-borrow(Tomcat JDBC)或connection-test-before-use(HikariCP 推荐用connection-init-sql或健康检测) - 设置合理的
max-lifetime和keepalive-time,避免使用过期连接
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











