LOAD_BALANCE=on未生效的根本原因是TNS解析未返回同一服务名下的多个地址。需确保tnsnames.ora中同一DESCRIPTION内配置多个ADDRESS且SERVICE_NAME完全一致(大小写敏感),并用tnsping验证是否解析出多地址;JDBC Thin驱动不支持该参数,RAC环境应优先使用SCAN而非手动列VIP。
LOAD_BALANCE=on 为什么没生效?
oracle 客户端的负载均衡不是开个开关就自动分发连接的,load_balance=on 只是前提,真正起作用依赖底层 tns 解析结果是否返回多个地址,且这些地址必须属于同一个服务名(即同一 service_name 或 sid 的多个实例)。如果 tnsnames.ora 里只写了一个地址,或者虽然写了多个但被解析成不同服务名(比如拼错 service_name),那 load_balance=on 就完全不触发。
- 检查
TNSNAMES.ORA中该别名下是否有多个(ADDRESS=...)条目,且都在同一个(DESCRIPTION=...)内 - 确认所有地址指向的是同一个数据库服务(
SERVICE_NAME值完全一致,大小写敏感) - 用
tnsping <alias>看输出里是否列出多个地址 —— 如果只显示一个,说明 TNS 解析失败或配置结构不对
tnsnames.ora 中多地址的正确写法
常见错误是把多个 ADDRESS 写成并列在顶层,或者混在不同 DESCRIPTION 里。Oracle 要求它们必须包裹在同一层 DESCRIPTION 下,否则客户端只会取第一个。
MYDB =
(DESCRIPTION =
(LOAD_BALANCE = on)
(ADDRESS = (PROTOCOL = TCP)(HOST = db1.example.com)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = db2.example.com)(PORT = 1521))
(CONNECT_DATA =
(SERVICE_NAME = orcl)
)
)
-
LOAD_BALANCE必须放在DESCRIPTION下,不能放在ADDRESS或CONNECT_DATA里 - 两个
ADDRESS是同级项,都直接属于DESCRIPTION,不是嵌套关系 - 如果用了
FAILOVER=on,它和LOAD_BALANCE=on可共存,但 failover 逻辑优先级更高 —— 连接失败才会切下一个,不是每次新建连接都轮询
连接时实际走哪个节点?怎么验证?
Oracle 客户端在建立连接时随机选择一个 ADDRESS(不是轮询),这个选择发生在客户端本地,不经过服务端协调。所以你无法靠日志直接看出“这次连的是 db1 还是 db2”,得从连接建立后查 V$SESSION 或 V$INSTANCE 确认。
- 连接成功后执行
SELECT INSTANCE_NAME FROM V$INSTANCE;,返回值就是实际所在的实例名 - 反复断开重连几次,观察返回值是否变化 —— 如果始终一样,说明
LOAD_BALANCE没生效,大概率是 TNS 配置结构或服务名不一致 - 注意:JDBC Thin 驱动默认不支持 TNSNAMES.ORA 中的
LOAD_BALANCE,它只认 URL 里的loadBalance=true参数,和本地 TNS 文件无关
LOAD_BALANCE 和 RAC、SCAN 的关系
如果你连的是 Oracle RAC,通常不该手动配多地址 + LOAD_BALANCE=on。RAC 推荐用 SCAN(Single Client Access Name)+ LOAD_BALANCE=on,或者更现代的方式是用 EZCONNECT 或 JDBC 的透明重试机制。手写多个 VIP 地址容易绕过 SCAN 的 DNS 负载和故障转移能力。
- SCAN 名称本身就是一个负载均衡入口,配合
LOAD_BALANCE=on才能发挥最大效果 - 如果误把 RAC 的各个节点 VIP 单独列在
TNSNAMES.ORA里,反而可能因节点宕机导致部分连接失败,而 SCAN 会自动剔除不可用节点 - 非 RAC 环境(比如 Data Guard 物理备库)不支持
LOAD_BALANCE,因为备库默认只读且不接受连接请求,强行配置会导致连接失败










