必须显式列出全部三个scan地址并配置loadbalance=true和failover=true,否则负载均衡失效;dns需返回三个a记录,jdbc驱动仅按url顺序连接首个地址。

只配一个 SCAN 地址,loadBalance=true 就是摆设——连接永远打到同一台节点,负载均衡完全失效。
SCAN 地址必须写全三个,且 DNS 必须返回全部 A 记录
Oracle RAC 的 SCAN 是 DNS 层面的轮询别名,但 JDBC Thin 驱动不查 SRV、不自动做 DNS 负载,它只按你 URL 里写的顺序连第一个地址。如果你写 jdbc:oracle:thin:@scan.example.com:1521/orcl,驱动就只连解析出的第一个 IP。
- 用
nslookup scan.example.com验证是否返回三个 A 记录;返回少于三个,说明 DNS 配置不完整 - 不要在 JDBC URL 中只写一个 SCAN 名——必须显式列出全部三个 SCAN 主机名或 IP,例如:
(ADDRESS=(HOST=scan1.example.com)(PORT=1521))、(ADDRESS=(HOST=scan2.example.com)(PORT=1521))、(ADDRESS=(HOST=scan3.example.com)(PORT=1521)) - 若用 IP 替代主机名,确保所有 SCAN IP 在客户端网络可达,且防火墙放行 1521 端口
JDBC URL 必须显式启用 loadBalance=true 和 failover=true
LOAD_BALANCE=on 写在 tnsnames.ora 里没用,JDBC 驱动只认 URL 参数;而且参数值必须是小写 true,不是 on 或 yes,否则被忽略。
- URL 中必须包含
?loadBalance=true&failover=true(注意是&,不是&) - 旧版驱动(如 ojdbc6)不支持该参数,12c 及以后版本(ojdbc8+)才真正生效
- Spring Boot 的
spring.datasource.url中直接拼接即可,但避免混用oracle.jdbc.url系统属性——它可能绕过 URL 解析逻辑 - 常见错误现象:
ORA-12170: TNS:Connect timeout反复出现,往往是因为第一个 SCAN 节点宕机,但驱动没切下一个地址
tnsnames.ora 方式更稳,但路径和权限极易出错
比起拼接长 URL,用 tnsnames.ora 文件配合 TNS_ADMIN 是 Oracle 官方推荐方式,尤其适合多集群、多服务名场景。
-
TNS_ADMIN必须指向包含tnsnames.ora的**父目录**,比如/etc/oracle/network,而不是/etc/oracle/network/tnsnames.ora - 文件中每个 SCAN 条目需独立命名(如
RACSCAN),JDBC URL 写成jdbc:oracle:thin:@RACSCAN - Java 进程启动前必须设置
TNS_ADMIN环境变量,application.properties或 JVM 参数里设无效 - Linux 下检查 SELinux 状态和文件权限:
ls -l /etc/oracle/network/tnsnames.ora,确保 JVM 运行用户有读取权限,否则静默失败、无日志提示
连接池配置会覆盖 RAC 的负载策略
即使 SCAN、URL、驱动全对,Druid/HikariCP 等连接池若配置不当,也会让所有连接扎堆到单个节点。
- 禁用连接池的“初始连接数”或“最小空闲连接”硬编码为 1——这会让池子只连第一个地址
- 确认连接池未开启“连接验证复用”或“连接缓存”类特性,它们可能绕过 JDBC 的地址轮询逻辑
- Druid 用户注意:
testWhileIdle和validConnectionCheckerClassName若误配,会导致健康检查失败后反复重试同一节点 - 最稳妥做法:在连接池外加一层简单日志,打印每次
DriverManager.getConnection()实际连的 IP(可从conn.getMetaData().getURL()提取)
SCAN 地址数量、DNS 解析结果、URL 参数大小写、TNS_ADMIN 路径层级、连接池初始化行为——这五点任意一个错位,都会让 RAC 的负载和故障转移形同虚设。实操时建议先用 sqlplus 验证 tnsnames 条目是否通,再迁移到 JDBC。











