1. 问题现象:一套RAC突然“半身不遂”
先交代一下现场。这套Oracle RAC跑的是19.16版本,双节点,操作系统是Oracle Linux 7.9,私网用的双千兆网卡绑定,走的是active-backup模式。这套库在机房跑了快两年,平时一直很稳,直到那天下午2点多,值班同事打电话过来,说应用侧开始间歇性报ORA-12570和ORA-03113,部分会话连接被重置。
我登录服务器检查,第一眼扫过去,两个节点的crsctl status resource -t显示集群资源一切正常,crsctl check cluster也是All OK。这里就有意思了——从应用侧看数据库确实在报错,但集群层面看起来什么事都没有。这个“表面正常”的状态本身就是最大的异常信号。
再往细里看去,问题开始浮出水面。
code复制crsctl stat res -t -init | grep -i gipc
gipc这个进程在init资源组里显示的是ONLINE,但它的状态那一栏带了一个括号备注,后面跟着一串INTERNAL ERROR之类的字样。其实对于RAC来说,gipc进程在刚启动或者网卡切换配置的瞬间,出现过短暂的INTERNAL状态并不稀奇,但如果它一直停留在那个状态不恢复,那问题就大了。这说明集群私网通信的内部通道已经处于“假活”状态——进程没死,但通讯能力已经废了。
紧接着我查了/var/log/oracle下的gipcd.log,果然里面刷满了类似这样的报错:
code复制2024-11-05 14:15:22.786: [GIPC][73793792]gipcmodNetworkBind: failed to bind to address 192.168.1.10, errno 22
2024-11-05 14:15:22.786: [GIPC][73793792]gipcmodOracleBind: failed
看到errno 22(EINVAL)基本就能确认,gipc在尝试绑定私网IP的时候出了问题。这个问题如果不尽快处理,下一步就是节点被集群驱逐(eviction),或者整个集群做 fence 重启。
所以这里是第一个踩坑点:排查RAC问题不能只看crsctl check cluster那一行OK到底的输出,Oracle自己的健康检查在私网通信故障时往往会短暂“失明”。必须逐项看进程状态、告警日志和gipc的详细日志,三个地方互相印证,才能看到真实情况。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 定位思路:从“进程假活”一路追到网卡层
既然确认了是gipc通讯异常,下一步就是沿着私网通信链路逐层往下找。
先说清楚这里面的逻辑链。RAC节点之间的心跳要走私网,私网通信由集群软件底层维护。在19c这套架构里,gipc进程负责建立和维护节点间的通信端点,它是整个私网通信的“底座”。gipc下面直接用socket收发数据包,socket挂在网卡的IP地址上。所以问题链条是:gipc进程异常 → socket绑定失败 → 私网IP不可用或状态异常 → 网卡或IP配置出问题。一条线下来,故障点基本就能锁定在网卡层。
我首先做的是在问题节点上重新初始化gipc,尝试让进程恢复。
code复制crsctl stop res ora.gipcd -init
crsctl start res ora.gipcd -init
操作结束后gipc进程恢复正常ONLINE,但过了不到20秒又开始报错,问题依旧。这里就基本排除了gipc进程自身的配置损坏可能,故障点一定在更底层——网卡或者IP。
接着看私网地址的状态:
code复制ip addr show
这里看到了关键异常:私网绑定的IP 192.168.1.10,对应的网卡状态显示为state DOWN。但诡异的是,IP地址本身还在网卡上,没有被移除。这个状态非常典型:IP还在,但网卡已经失活,数据包发不出去也收不进来。gipc的socket自然也就无法正常工作。
这时候我上了第二招,用ethtool看网卡的物理链路状态:
code复制ethtool eth1 | grep -E "Speed|Duplex|Link detected"
输出显示Link detected: yes,速度和双工模式也正常。这就说明网卡物理层没问题,链路是通的。那问题就出在协议栈或者绑定配置层面,而不是硬件电缆。
再查绑定模式:
code复制cat /proc/net/bonding/bond0
看到当前活动网卡是eth1,备用是eth2,active-backup模式。到这里,问题链路变得清晰:网卡物理链路正常,但IP所在的主网卡被标记为DOWN,导致IP虽然存在却无法通信。接下来就是搞明白为什么网卡会被系统置为DOWN。
3. 深入底层:操作系统网卡状态与Oracle私网配置的“双盲区”
这里有个很典型的运维盲区,我必须单独拿出来说。很多DBA排查RAC网络问题,习惯性只盯crsctl和ifconfig,但对操作系统层面的网卡管理机制了解不够细,容易卡在“物理链路正常但IP不通信”这种诡异状态里。
在Oracle Linux 7.9上,网卡的管理默认由NetworkManager或者systemd-networkd负责。对于绑定网卡,系统通过/etc/sysconfig/network-scripts/ifcfg-bond0这类配置文件来管理。而在Oracle RAC 19c安装过程中,有一个非常容易出问题的地方——Oracle自身的私有网络配置会和操作系统的网卡管理机制产生“争夺”。
Oracle的grid setup阶段会调用oifcfg来设置集群私网网卡,同时它会修改/etc/sysconfig/network-scripts/下的网卡配置文件,把Oracle私网网卡标记为“不自动激活”或者加入特殊参数,用来防止网卡重启后被NetworkManager重复接管。这些改动在实际生产里一旦遇到系统补丁升级、网卡驱动加载顺序变化、或者NetworkManager的运行状态改变,就非常容易出现网卡被系统错误标记为DOWN的情况。
我这次查到的就是这个原因。
code复制systemctl status NetworkManager
输出显示NetworkManager在运行。而Oracle RAC的私网网卡在安装时一般会按照官方建议,在ifcfg文件里加上NM_CONTROLLED=no来避免被NetworkManager管控。但因为系统之前打过一轮kernel和驱动补丁,网卡驱动重新加载时,NetworkManager在启动阶段接管了bond0,随后又因为配置冲突把bond0置为DOWN——但IP还在。这个状态就是“IP残留、链路失效”的真相。
确认到这里,整个问题的根因链路就完整了:系统补丁后NetworkManager与Oracle私网网卡配置产生冲突 → 网卡bond0被错误置为DOWN → 私网IP虽然还在但实际无法通信 → gipc绑定失败、socket失效 → 集群私网心跳异常 → 应用侧大量连接错误。
这是一个典型的“DBA视角正常、OS视角异常”的双盲区问题。不深入到底层,很容易在gipc或crsctl层面反复重启、反复观望,白白浪费窗口期。
4. 解决过程:从快速止血到永久修复
定位到这一步,解决方案就清晰了。我的处理思路分两步走:先快速恢复通信,再彻底修复配置,避免问题复现。
4.1 紧急恢复通信
首选方案是直接把bond0拉起。
code复制ifup bond0
执行后立刻看ip addr show里bond0的状态,确实变成了state UP,私网IP从DOWN状态恢复了正常。再观察gipc日志,报错停止刷新,gipc在几分钟内自动重新建立了socket绑定。再用crsctl check cluster检查,这次才是真正意义上的All OK。
这里补充一句,紧急恢复阶段不要重启整个集群或者做crsctl stop/start全量重启。在私网通信有问题的状态下,重启集群资源存在节点驱逐风险,反而会把一个网卡问题放大成数据库不可用事故。最优先的做法是恢复底层网络,让gipc进程自己重新收敛。
4.2 永久修复NetworkManager冲突
恢复通信只是把火扑了,接下来得把“火灾隐患”拆掉。
我做的修复是修改私网网卡的ifcfg配置文件,明确禁止NetworkManager接管私网网卡。对于Oracle Linux 7.x,私网网卡对应的是bond0,确保以下配置存在:
code复制# /etc/sysconfig/network-scripts/ifcfg-bond0
DEVICE=bond0
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=none
NM_CONTROLLED=no
IPADDR=192.168.1.10
NETMASK=255.255.255.0
BONDING_MASTER=yes
BONDING_OPTS="mode=active-backup miimon=100"
关键在于NM_CONTROLLED=no——这条参数明确告诉NetworkManager不要管这个网卡。我之前遇到过不少环境里这个参数被安装脚本漏配,或者被系统升级重置的情况。检查的时候顺手把两个子网卡eth1、eth2的配置也查了一遍,同样都补上了NM_CONTROLLED=no。
由于这套系统本身就开启了NetworkManager,而Oracle RAC私网网卡又不希望被它管理,所以修改完配置后需要重启NetworkManager服务。
code复制systemctl restart NetworkManager
重启后确认bond0没有被重新拉DOWN,私网通信持续稳定。之后再手动重启gipc进程做一次干净的状态切换,确认日志无报错。
4.3 用oifcfg做配置一致性校验
修复完系统层之后,我还做了一次Oracle层面的私网配置校验,确保集群认识的私网网卡和实际操作系统的网卡是同一个。
code复制$GRID_HOME/bin/oifcfg iflist
$GRID_HOME/bin/oifcfg getif
iflist显示系统识别到的可用网卡列表,getif显示集群当前记录的私网/公网网卡关系。我检查了cluster_interconnect和public两者的对应关系,确认私网指向的是bond0。这里有个细节:如果oifcfg iflist输出中缺少某个网卡,或者显示的IP和实际配置不一致,生产环境里经常导致节点反复重启或者节点驱逐。这一项必须纳入排查清单。
5. 复盘:这几类“隐性网卡故障”最容易坑RAC
这次问题处理完,我整理了RAC私网网卡故障的几个典型坑,分享出来供参考。
| 故障类型 | 外在表现 | 排查要点 |
|---|---|---|
| 网卡被NetworkManager误置DOWN | IP还在、物理链路正常,但私网不通 | 必查ip addr show里的state、systemctl status NetworkManager |
| 绑定网卡主备切换后IP未跟随 | gipc日志大量bind失败,但eth0正常 | 检查/proc/net/bonding/bond0的主备状态与IP归属 |
| 私网网卡MTU不一致 | 大包心跳丢包、gipc间歇性告警 | 两节点ping -M do -s 8972对测私网IP |
| 网卡驱动升级后协议栈异常 | 网卡link up但丢包率极高 | ethtool -S查rx_dropped、netstat -i查错误计数 |
| 私网跨交换机但未做端口聚合 | 单条链路故障导致整个私网中断 | 检查私网链路是否跨物理设备、是否配置LACP |
其中ping -M do -s 8972这个命令是Oracle私网MTU检查的标准动作,因为私网在19c里默认MTU是9000,加上IP和ICMP头就是8972字节的有效载荷。两节点互相ping这个大小的包不丢包不分片,说明私网大包通信没问题。这一步在网卡或交换机变更后一定要做,我见过太多“小包通、大包断”的隐蔽故障被忽略。
另外还要提醒一点:Oracle 19c的gipc日志位置和12c有所不同,默认在$GRID_BASE/diag/tnsnames/gipcd或者/var/log/oracle下。排查时直接用crsctl stat res ora.gipcd -init -v查看GIPCD_HOME参数确定日志目录,不要浪费时间在旧路径里找半天。
6. 几个实用的预防建议
经历过这次故障之后,我给自己维护的每套RAC都加了几条例行检查项,这里分享出来。
第一,定期核对网卡配置文件里的NM_CONTROLLED=no是否完好。尤其是操作系统升级、驱动更新、安全加固脚本执行过后,这个参数被改动是大概率事件。建议每季度巡检一次,用自动化脚本巡检所有RAC节点的网卡配置,比对关键参数。
第二,维护窗口内主动演练一次私网主备切换。active-backup模式下的绑定网卡,可以手动切换主备链路测试,确认IP地址能正确跟随网卡切换,gipc不会因为切换而长时间中断。这个测试在业务低峰期做,时间窗口控制在几分钟内,风险很小,但如果从来没测过,出事时才发现切换逻辑有问题,那代价就大了。
第三,在zabbix或者自研监控平台里加上对bond0链路状态的独立监控。Oracle的crsctl监控反应太慢,只有当节点被驱逐时才会告警。而网卡down这种状态,用ip addr show里的state字段就能直接判断,这个监控项实现难度低、回报极高,建议所有RAC环境都加上。
第四,针对私网单点链路风险做一次架构审视。如果私网只走了单个交换机,那交换机端口故障、交换机整机重启这类事件会导致两节点同时失联,这是RAC最怕的“脑裂”场景。有条件的话,私网建议跨两台交换机做端口聚合,或者至少保证两个节点直连互联。很多生产事故追根溯源都是私网物理链路的单点问题,运维投入不大,但收益实打实。
我从这次故障里最大的体会是:RAC排障走到最后,拼的不是对Oracle某个视图的熟悉程度,而是对操作系统底层网络栈的理解。gipc只是最上层的“报警器”,它报错背后的网卡状态、绑定配置、NetworkManager策略,才是真正需要反复推敲的地方。很多数据库层面的疑难杂症,往回追两层,答案往往在操作系统里等着你。
