问题根源在OS层NFS挂载的OCR磁盘无响应,导致CSSD心跳超时、集群驱逐与节点假死,而非数据库负载问题。
单节点CPU负载高但DB Time很低,说明问题不在数据库层
看到 db time 占比不到 1%,平均会话数 161、cpu 有 128 核,却出现系统夯死、rcu_sched self-detected stall on cpu 报错——这基本排除了 sql 或并发导致的数据库级过载。真正的问题藏在 os 层:nfs 挂载的 ocr 磁盘无响应 → cssd 心跳超时 → 集群判定节点失联 → 启动驱逐 → 但此时节点已假死,无法自动恢复。
- 务必先查
/var/log/messages是否有nfs: server not responding, still trying - 用
top -H或pidstat -t 1看是否大量线程卡在D(不可中断)状态,尤其是和 NFS、block I/O 相关的进程 - OCR 不该走 NFS;生产环境必须使用 ASM 或本地块设备(如 iSCSI/FC),NFS 仅限测试验证
客户端 TNS 配置 load_balance=on 不等于真负载均衡
只在客户端 tnsnames.ora 里加 LOAD_BALANCE = yes,只是让 Oracle Net 随机挑一个 VIP 连接,属于“连接时负载均衡”——它不感知后端实例真实负载,也不做连接复用或重定向。如果所有应用都连到同一个实例(比如因 DNS 缓存、VIP 漂移异常或监听未启用),LOAD_BALANCE 就形同虚设。
- 确认两个实例监听都正常:
lsnrctl status LISTENER在各自节点执行,检查SERVICE_NAME是否注册成功 - 连接串中必须包含全部 VIP 地址(不是 SCAN IP)且顺序无关:
(ADDRESS=(PROTOCOL=TCP)(HOST=node1-vip)(PORT=1521))和(ADDRESS=(PROTOCOL=TCP)(HOST=node2-vip)(PORT=1521)) - 避免混用 SCAN 和 VIP:SCAN 用于服务名注册与故障转移,VIP 才是 TAF 实际 failover 的目标地址;混用可能导致 TAF 跳转失败
TAF 配置生效的前提是服务端 SERVICE + 客户端 FAILOVER_MODE 双匹配
TAF 不是“开个开关就自动续命”的功能。它依赖服务端定义的 srvctl add service 中的 -y AUTOMATIC 和 -e SELECT,同时客户端 TNS 必须显式声明 FAILOVER_MODE,否则即使连接断了,SQL*Plus 也会直接报错退出,不会尝试切换。
- 服务端创建 service 时,
-r列表必须包含所有可承载流量的实例,-a是 fallback 实例(非必需);漏写任一实例会导致该节点永远收不到新连接 - 客户端 TNS 必须写全:
(FAILOVER_MODE=(TYPE=select)(METHOD=basic)(RETRIES=10)(DELAY=3)),缺任意一项,TAF 就不触发 - JDBC 驱动默认禁用 TAF;若要用,需在 URL 加
&oracle.net.enableOob=true&oracle.net.disableOob=false并设置ConnectionProperties,但实测稳定性远不如 SQL*Plus
节点假死后 TAF 无法挽救,必须靠集群健康机制兜底
当节点操作系统级卡死(如 NFS hang 引发 RCU stall),CSSD 进程无法发送心跳、CRSD 无法上报状态、监听进程虽存活但拒绝新连接——这时客户端即使配了完美 TAF,也只会不断重试原 VIP 直到超时,根本等不到“failover”。TAF 只处理“实例崩溃”或“监听宕掉”,不处理“OS 假死”。
- 监控不能只盯
GV$INSTANCE状态,必须叠加 OS 层指标:vmstat 1的run queue长期 > CPU 核数 × 2、iostat -x 1的%util持续 100% 且await> 100ms,就是危险信号 - OCR/Voting Disk 必须放在低延迟、高可用存储上;NFS 挂载点要加
hard,intr,nofail,_netdev,但最好彻底不用 - 别指望 TAF 替代 HA:节点级故障必须由 Clusterware 自动 fencing + reboot,而不是靠客户端重连扛过去
showmount -e $nfs_server 能否列出共享、rpcinfo -p $nfs_server 是否返回 portmap 映射。这点一漏,后面所有 TAF 和负载均衡配置都白搭。










