LOAD_BALANCE=on必须置于每个DESCRIPTION块内且紧邻ADDRESS后,放错位置(如CONNECT_DATA内或DESCRIPTION_LIST外层)会导致连接全打首节点;仅配SCAN地址时该参数无效。

LOAD_BALANCE=on 放错位置,连接全打第一个节点
大数据量导入时连接扎堆,往往不是数据库没负载均衡能力,而是客户端根本没启用它。关键在 LOAD_BALANCE=on 的位置——必须放在每个 DESCRIPTION 块内、紧邻 ADDRESS 之后,不能塞进 CONNECT_DATA,也不能挂在 DESCRIPTION_LIST 外层。
常见错误写法:(DESCRIPTION=(ADDRESS=...)(CONNECT_DATA=...)(LOAD_BALANCE=on)) → 不生效(DESCRIPTION_LIST=(LOAD_BALANCE=on)(DESCRIPTION=(ADDRESS=...)(CONNECT_DATA=...))) → 仅对第一个 ADDRESS 生效
正确结构必须用 DESCRIPTION_LIST 包裹多个独立的 DESCRIPTION,且每个都带自己的 LOAD_BALANCE=on:
(DESCRIPTION_LIST= (DESCRIPTION=(ADDRESS=(HOST=rac1-vip)(PORT=1521))(LOAD_BALANCE=on)(CONNECT_DATA=(SERVICE_NAME=mydb))) (DESCRIPTION=(ADDRESS=(HOST=rac2-vip)(PORT=1521))(LOAD_BALANCE=on)(CONNECT_DATA=(SERVICE_NAME=mydb))) )
只配 SCAN 地址(如 HOST=rac-scan)时,LOAD_BALANCE=on 无效——TNS 没得可选,直接忽略。
REMOTE_LISTENER 指向错误或未刷新,SCAN Listener 看不到真实负载
服务器端负载均衡靠 PMON 每 3 秒向 REMOTE_LISTENER 上报 V$SERVICEMETRIC.CURRENT_LOAD,但前提是 REMOTE_LISTENER 指向的是 SCAN VIP(不是节点 VIP、localhost 或 GNS VIP 错位)。
验证要点:
- 查
lsnrctl status LISTENER_SCAN1输出中,对应服务条目是否含load=xx字段(例如service_handler="DEDICATED", load=12) - 执行
ALTER SYSTEM REGISTER强制刷新,否则 PMON 可能延迟数分钟才推送新负载 - 确认
V$SERVICES.LOAD_BALANCE列为YES:SELECT name, load_balance FROM gv$services WHERE name = 'mydb';
若 SCAN Listener 始终显示 load=0 或缺失该字段,说明上报链路中断,所有连接将退化为 round-robin,无法按真实负载分发。
连接池预热导致初始连接全部落在同一实例
大数据量导入常伴随连接池批量建连(如 HikariCP 的 minimumIdle、UCP 的 initialPoolSize),此时 DNS 缓存未刷新或 TNS 解析结果固定(SCAN 返回 IP 顺序不变),会导致所有连接在启动瞬间落到同一个实例。
这不是配置错误,是时间窗口问题,解决方式包括:
- 禁用连接池预热:设
minimumIdle=0,让连接随实际导入请求懒加载 - 强制 TNS 解析随机化:在 JDBC URL 中显式使用多个 VIP 地址(而非 SCAN),并确保每个
DESCRIPTION都带LOAD_BALANCE=on - 导入前执行一次空连接探活:
SELECT 1 FROM DUAL,触发 TNS 解析并缓存多个地址路径
注意:Oracle 19c+ 的 SCAN 默认返回 IP 顺序稳定,不主动轮换,依赖客户端解析逻辑而非 DNS 轮询。
AWR 中真正暴露负载不均的是 GC 统计,不是 CPU 或会话数
导入期间某节点 CPU 高,不代表它过载;真正失衡信号藏在 AWR 的 RAC Statistics 部分,而非 Instance Activity Stats。
重点关注四列(单位:块/秒):
-
gc cr blocks received:从其他节点拉取一致性读块数量 -
gc current blocks received:从其他节点拉取当前块数量 -
gc cr blocks served:本节点向外提供一致性读块数量 -
gc current blocks served:本节点向外提供当前块数量
典型偏斜模式:
- 某节点
received远大于served→ 它本地缓存不足,被动拉数据,可能因绑定变量倾斜或大表广播 - 某节点
served远大于received→ 它是热点持有者,被频繁请求,需检查索引分布或分区键设计
用 gv$sysstat 实时验证:SELECT inst_id, name, value FROM gv$sysstat WHERE name IN ('gc cr blocks received','gc current blocks received','gc cr blocks served','gc current blocks served'); ——务必带 inst_id,否则 sum() 会掩盖偏斜。


















