LOAD_BALANCE=on必须置于DESCRIPTION层级,不能在CONNECT_DATA内;若放错位置,客户端连接将全部路由至首个节点。
LOAD_BALANCE=on 必须放在 DESCRIPTION 级,不是 CONNECT_DATA 里
客户端连接不分散,全打到第一个节点?大概率是 load_balance=on 放错了位置。它只能出现在 description 节点下,且必须紧邻 address 块之后、connect_data 之前。
错误写法(无效):
MYDB = (DESCRIPTION = (ADDRESS = (PROTOCOL=TCP)(HOST=scan.example.com)(PORT=1521)) (CONNECT_DATA = (SERVICE_NAME=mydb) (LOAD_BALANCE=on)) ← 这里不认 )
正确写法(生效):
MYDB = (DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL=TCP)(HOST=scan.example.com)(PORT=1521))
(LOAD_BALANCE = on) ← 必须在这层,且是单个 DESCRIPTION 的直属属性
(CONNECT_DATA = (SERVICE_NAME=mydb))
)
)
- 如果用了多个
ADDRESS(比如直连两个 VIP),每个DESCRIPTION都要单独加LOAD_BALANCE=on,否则只对第一个地址生效 - Java 应用用 UCP 或 OJDBC 时,该参数仍由本地 TNS 解析器读取,
jdbc:oracle:thin:@...URL 里加了也没用 -
DESCRIPTION_LIST不是必须的,但用了就别漏掉括号层级;漏一层括号会导致 TNS 解析失败,报ORA-12154
REMOTE_LISTENER 指向 SCAN,且必须执行 ALTER SYSTEM REGISTER
服务端不注册负载信息,客户端再怎么随机选地址,最终也只会被 SCAN Listener 分发到默认或唯一在线的实例上——因为 Listener 根本不知道其他节点忙不忙。
检查是否生效的最直接方式:
$ lsnrctl status LISTENER_SCAN1 | grep -A 5 "Service \"mydb\""
如果输出中只有 DEDICATED handler、没有 LOAD 字段和实例负载值(如 LOAD=23),说明注册失败。
-
REMOTE_LISTENER必须设为 SCAN 地址,例如:ALTER SYSTEM SET REMOTE_LISTENER='scan.example.com:1521' SCOPE=BOTH; - 改完参数后,必须立刻执行:
ALTER SYSTEM REGISTER;—— PMON 不会等下次自动刷新,不手动触发就不会上报新负载 - 若环境启用了 GNS,
REMOTE_LISTENER要指向 GNS VIP,而非 SCAN;否则注册静默失败,无报错也无日志提示 - 用
srvctl config listener确认 SCAN Listener 是否真正运行并监听在预期端口
别让 FAILOVER_MODE 干扰负载分发逻辑
加了 FAILOVER_MODE 的 TNS 配置,常导致连接行为异常:看似在做负载均衡,实则反复重试、连接卡住、甚至报 ORA-12545。这是因为故障转移机制会覆盖连接选择策略。
典型干扰配置:
(FAILOVER_MODE = (TYPE = session)(METHOD = basic)(RETRIES = 180)(DELAY = 5))
-
FAILOVER_MODE和LOAD_BALANCE=on逻辑冲突:前者要求“先连一个,挂了再换”,后者要求“每次新建连接都重新选” - 生产环境若需故障转移,应优先通过 Service 层(
srvctl add service -failovertype ...)实现,而不是在客户端 TNS 里硬编码 - 测试负载均衡效果时,务必先注释掉整个
FAILOVER_MODE块,排除干扰 - Java 应用若用 UCP 连接池,其内置的故障转移已足够,TNS 中再配反而降低首次连接成功率
单机多实例场景下,Listener 交叉监听需靠 SERVICE + INSTANCE 绑定
单机部署多个 RAC 实例(如开发/测试环境),想让不同实例响应不同服务名的请求,不能只靠 ADDRESS 列表轮询——那是跨节点的玩法。这里得靠 Service 映射和 PMON 主动注册。
关键操作链:
- 为每个实例创建专属 Service:
srvctl add service -d mydb -s svc_inst1 -r mydb1 -a mydb2 - 确保每个实例的
INSTANCE_NAME在init.ora或 SPFILE 中明确区分(如mydb1/mydb2) - Service 启动后,PMON 会自动向本地 Listener 注册该实例能响应的服务名,无需额外配置
listener.ora的SID_LIST - 客户端 TNS 只需指定对应服务名:
(SERVICE_NAME = svc_inst1),Listener 就只会把请求转给注册了该 Service 的实例 - 验证注册结果:
lsnrctl services LISTENER,看输出中各 Service 下绑定的INSTANCE_NAME是否准确
这种模式下,“负载均衡”实际是人工划分的静态路由,但比盲目轮询更可控,也避免了 Cache Fusion 带来的性能抖动。











