Load Balance设置失效的典型表现是连接池连接始终集中于单一RAC实例,根本原因是TNS描述符未在ADDRESS_LIST内层配置LOAD_BALANCE=on或SCAN监听器未正确注册实例负载信息。
Load Balance 设置失效的典型表现
连接池(比如 ucp、hikaricp 或 weblogic 的 jdbc 连接池)配置了 loadbalance=true,但实际连接始终只打到某一个 rac 实例(如 rac1),v$session 中看不到跨实例的连接分布,tnsping 显示服务名解析正常,但负载就是不均衡。
检查 TNS 描述符中是否启用客户端负载均衡
Oracle 客户端负载均衡依赖 TNS 层的 LOAD_BALANCE=on 参数,不是 JDBC URL 里加个 loadBalance=true 就生效的。JDBC 驱动只是透传或配合该行为。
-
tnsnames.ora或 JDBC URL 中的 TNS 字符串必须包含(LOAD_BALANCE=on),且放在(ADDRESS_LIST=...)内部 - 错误写法:
(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=rac-scan)(PORT=1521))...)—— 缺少ADDRESS_LIST容器,LOAD_BALANCE无效 - 正确结构示例:
(ADDRESS_LIST= (LOAD_BALANCE=on) (ADDRESS=(PROTOCOL=TCP)(HOST=rac1-vip)(PORT=1521)) (ADDRESS=(PROTOCOL=TCP)(HOST=rac2-vip)(PORT=1521)) )
- 若用 SCAN 地址,确保 SCAN listener 确实注册了所有实例,且
REMOTE_LISTENER和LOCAL_LISTENER配置无误 —— 否则即使LOAD_BALANCE=on,SCAN 也只会返回一个地址
JDBC URL 中的 loadBalance 参数仅作用于连接建立阶段
loadBalance=true 是 Oracle JDBC 驱动(ojdbc8+)的连接属性,它只影响“新建连接时”从多个地址中随机选一个;它不控制已有连接的重路由,也不参与运行时的请求分发。
- 连接池初始化时可能批量建连,若 DNS 缓存或 TNS 解析结果固定(比如 SCAN 返回 IP 顺序不变),仍会集中到同一实例
- 连接池复用连接后,所有 SQL 请求都走原连接,和负载均衡无关 —— RAC 的服务名负载均衡是连接级的,不是语句级的
- 真正影响连接分布的是:TNS 解析结果 +
LOAD_BALANCE=on+ 客户端驱动版本(ojdbc8.jar18c+ 才完整支持 SCAN + LB 组合) - 验证方式:在应用启动后立刻查
v$session的inst_id,看连接是否分散;不要等运行几小时后再判断
连接池自身干扰:预热/最小连接数导致 LB 失效
很多连接池(如 HikariCP)默认开启 connectionInitSql 或设置 minimumIdle > 0,会在启动时主动建立一批连接。如果此时 TNS 解析未刷新或 DNS 缓存未失效,这批连接大概率全落在同一个实例上。
- 临时解决:启动前清空本地 DNS 缓存(
sudo systemd-resolve --flush-caches或 Windows 上ipconfig /flushdns) - 更可靠做法:把连接池的
minimumIdle设为 0,让连接按需懒创建,配合 TNS 的LOAD_BALANCE=on才能体现随机性 - UCP 用户注意:
setInitialPoolSize(0)并不等于禁用预热,需同时设setMinPoolSize(0)和关闭setValidateConnectionOnBorrow(false)避免 borrow 时触发批量验证连接 - 别忽略 Oracle 服务端的
FAILOVER_MODE设置 —— 如果启用了TYPE=SESSION,连接池可能因失败重试逻辑反复连同一实例,掩盖 LB 行为
ADDRESS_LIST 或 SCAN 配置异常;剩下 10% 是连接池过早预热固化了连接分布。改完配置后,一定要重启应用进程 —— JVM 不会自动 reload tnsnames.ora 或重新解析 SCAN。


















