java应用在oracle主备切换后无法自动恢复连接,根本原因是jdbc thin驱动默认忽略taf通知、不解析failover_mode参数,且连接池未清理僵尸连接;须启用alt(enablealt=true&altlevel=u)、配置connection-test-query及validation-timeout,并确保数据库侧alt_grace_period已设非零值。

ORA-03113 报出来就说明连接已断,但 Java 应用没重连——这不是网络不通,而是 JDBC 驱动和连接池根本没触发重建逻辑。Oracle 主备切换后“连不上”,90% 的情况不是数据库问题,是 Java 层配置缺位。
Thin 驱动默认无视 TAF 和 FAILOVER_MODE
Oracle 官方 JDBC Thin 驱动从设计上就不支持 TAF(Transparent Application Failover)回调。哪怕你在 tnsnames.ora 或 JDBC URL 里写了 (FAILOVER_MODE=(TYPE=SELECT)(METHOD=BASIC)),它也完全不解析、不注册监听器、不重试、不重放语句。
- 验证方法:抓包看切换后是否发起新 TCP 连接——没有,就证明驱动静默失败
-
OCI驱动才真正支持 TAF,但 Java Web 应用几乎不用(要部署oci.dll+ 环境变量) - 别信“加了 FAILOVER_MODE 就能自动恢复”的说法,对 Thin 驱动就是无效配置
HikariCP / Druid 不清理僵尸连接,复用即报错
切换后旧连接的 socket 已被关闭,但连接池不知道,仍把它当作可用连接返回给业务线程。第一次执行 SQL 时直接抛 SQLException: Closed Connection 或 IO Error: Connection reset,而不是去建新连接。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- HikariCP 默认关闭借用前校验:
connection-test-before-use=false,validationQuery实际不生效 - 必须显式开启:
connection-test-before-use=true,且配connection-test-query=SELECT 1 FROM DUAL - Druid 要设
testWhileIdle=true+timeBetweenEvictionRunsMillis=30000,否则空闲连接永远不探活 - 光靠
autoReconnect=true没用——这是 MySQL 驱动参数,Oracle JDBC 完全忽略
ALT(Application-Level Transparency)不是可选项,是必开项
想让 Thin 驱动在主备切换后“感知并重建”,唯一可行路径是启用 ALT(注意:非 Oracle 原生,而是 GaussDB/部分国产 Oracle 兼容库引入的增强机制,但已被主流 JDBC 驱动适配)。
- JDBC URL 必须带:
&enableALT=true&altLevel=U,缺一不可 - 数据库侧必须设
alt_grace_period=60(单位秒),且重启实例生效 - 单节点地址(如
jdbc:oracle:thin:@host:1521/orcl)无法触发 ALT;必须用多节点格式:jdbc:gaussdb://node1,node2,node3/orcl -
targetServerType=master单独存在无效,必须和 ALT 参数叠加才起作用
service_names 没同步注册,连都连不到新主库
容灾切换完成后,新主库默认只注册 db_unique_name 对应的服务名(比如 jiekexu),而你应用连接用的是自定义 service(如 orcl_svc),监听器里压根没这个服务——结果就是稳定报 ORA-12516: TNS:listener could not hand off client connection。
- 不能靠客户端加
RETRY_COUNT硬扛,重试十次连的还是不存在的服务名 - 必须在新主库上执行:
ALTER SYSTEM SET service_names='orcl_svc,scott' SCOPE=BOTH - 再立刻执行:
ALTER SYSTEM REGISTER(触发 PMON 推送,无需重启监听) - 切完脚本里漏掉这两句,等于白切——很多团队卡在这一步长达数小时
service_names 改了但忘了 ALTER SYSTEM REGISTER、连接池开了 validationQuery 却没开 connection-test-before-use。每个环节都得实打实验证,少一个,切换后照样挂。Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










