Oracle集群新特性竟然导致正常节点被踢出集群

突发故障,集群两个节点同时重启

某天深夜突然接到客户电话,集群脑裂导致集群2个节点在3分钟内先后重启,影响了业务。按照正常情况,脑裂只会踢出一个节点,两个节点分别重启的现象倒是比较少见。不由得让我好奇心大起,拿到客户提供的日志立即着手分析。

OSW收集到的数据,故障的时间线大致如下:

21:42:29开始,节点2日志采集中断,OS夯住导致操作系统命令无法正常执行。
21:44:12左右,节点1报出通讯错误,和节点1之间的通讯发生中断。

2024-06-19 21:44:27.744 [OCSSD(26526)]CRS-1612: Network communication with node orcldb02 (2) missing for 50% of timeout interval.  Removal of this node from cluster in 14.830 seconds
2024-06-19 21:44:35.745 [OCSSD(26526)]CRS-1611: Network communication with node orcldb02 (2) missing for 75% of timeout interval.  Removal of this node from cluster in 6.830 seconds
2024-06-19 21:44:39.745 [OCSSD(26526)]CRS-1610: Network communication with node orcldb02 (2) missing for 90% of timeout interval.  Removal of this node from cluster in 2.830 seconds

看到以上信息,有经验的DBA都知道系统发生了脑裂,集群发生脑裂后会选择其中的一个节点踢出集群。按照正常的逻辑,节点2被踢出集群是预期行为,首先节点2已经出现操作系统夯住的异常,其次对于两个节点的集群,即使两个节点都没有明显的问题,Oracle也会优先保留id更小的那个,因此不论是什么情况节点2都会是被踢出集群的那个。但诡异的是在随后的集群配置过程中节点1也被踢出集群!

在节点1的ocssd.trc文件中,我们找到了节点被踢出集群的决策过程。

2024-06-19 21:44:42.576 :    CSSD:3183412992: clssnmMarkNodeForRemoval: node 2, orcldb02 marked for removal

--开始进行权重计算
2024-06-19 21:44:42.577 :GIPCWAIT:3178682112: gipcWaitStartWait: starting as primary waiter ctx 0x10e1d90 [000000000000025d] { gipcContext : traceLevel 5, fieldLevel 0x0, numDead 1, numPending 0, numZombie 0, numObj 10, numWait 0, numReady 0, wobj 0x1101ac0, hgid 000000000000025e, flags 0x2e, objFlags 0x0 }
2024-06-19 21:44:42.577 :    CSSD:3180259072: clssnmCompareNodeWeights: count(1), low(1), bestcount(0), best_low(65535), cur_weight: pebbles(0) goldstars(0) pubnw(0) flexasm(0) nopvtnw(0) best_weight: pebbles(0) goldstars(0)pubnw(0) flexasm(0)  nopvtnw(0)
2024-06-19 21:44:42.577 :    CSSD:3180259072: clssnmCompareNodeWeights: Changing the best map: Reason: 4
2024-06-19 21:44:42.577 :    CSSD:3180259072: clssnmFindBestMap: Using base map(1) of node(1) count(1), low(1), bestcount(1), best_low(1), cur_weightpebbles (0) goldstars (0) flags (0) SpoolVersion (0)best_weightpebbles (0) goldstars (0) flags (0) SpoolVersion (0)

--node2此时CRS已经是dead状态,但node1在计算权重时仍然在等待node2更新自己的权重
2024-06-19 21:45:37.138 :    CSSD:3180259072: clssnmrCheckNodeWeight: node(1) has weight stamp(566738892) pebbles (0) goldstars (0) flags (3) SpoolVersion (0)
2024-06-19 21:45:37.138 :    CSSD:3180259072: clssnmrCheckNodeWeight: node(2) has weight stamp(0) pebbles (0) goldstars (0) flags (0) SpoolVersion (0)
2024-06-19 21:45:37.138 :    CSSD:3180259072: clssnmrCheckNodeWeight: Server pool version not consistent
2024-06-19 21:45:37.138 :    CSSD:3180259072: clssnmrCheckNodeWeight: stamp(566738892), completed(1/2)
2024-06-19 21:45:37.138 :    CSSD:3180259072: clssnmrCheckSplit: Waiting for node weights, stamp(566738892)
2024-06-19 21:45:37.138 :    CSSD:3180259072: clssnmrCheckNodeWeight: Node weight stamp checking bypassed
2024-06-19 21:45:37.138 :    CSSD:3180259072: clssnmrCheckNodeWeight: node(1) has weight stamp(566738892) pebbles (0) goldstars (0) flags (3) SpoolVersion (0)
2024-06-19 21:45:37.138 :    CSSD:3180259072: clssnmrCheckNodeWeight: node(2) has weight stamp(566738891) pebbles (1) goldstars (0) flags (3) SpoolVersion (0)
2024-06-19 21:45:37.138 :    CSSD:3180259072: clssnmrCheckNodeWeight: Server pool version not consistent
2024-06-19 21:45:37.138 :    CSSD:3180259072: clssnmrCheckNodeWeight: stamp(566738892), completed(1/2)

--最后等待超时,CRS使用旧的权重信息
2024-06-19 21:45:37.138 :    CSSD:3180259072: clssnmrCheckSplit: Wait timeout for nodeweights, exceeded for stamp(566738892) Copied weights available in the nodeDB
……
2024-06-19 21:45:37.139 :    CSSD:3180259072: clssnmCheckDskInfo: My cohort: 1
2024-06-19 21:45:37.139 :    CSSD:3180259072: clssnmCheckDskInfo: Surviving cohort: 2
2024-06-19 21:45:37.139 :    CSSD:3180259072: clssnmChangeState: oldstate 3 newstate 0 clssnmr.c 2755

--CRS abort了自己
2024-06-19 21:45:37.139 :    CSSD:3180259072: (:CSSNM00008:)clssnmCheckDskInfo: Aborting local node to avoid splitbrain. Cohort of 1 nodes with leader 1, orcldb01, loses to cohort of 1 nodes led by node 2, orcldb02, based on map type 2 since the cohort has higher cumulative pebbles weight

上面的日志分析过程,我加了一些备注,相信大家已经看明白了。和之前不同的是,这次的决策过程中提到了NodeWeights,系统使用节点2旧的权重进行集群决策,不凑巧的是节点2的权重比节点1的权重要高,因此把正常的节点1踢出了集群。

事实上,几乎就在节点1将自己踢出集群之前的几秒钟,节点2的OS已经发生了重启,于是就发生了文前提到的那一幕。

原来是新特性惹的祸

关于NodeWeights,源自于Oracle 12.1.0.2中引入的一个新特性,在这之前脑裂发生时会优先保留更小的节点,从12.1.0.2开始,Oracle会优先保留权重更高的节点。虽然没有公布计算节点权重的算法,但这个方案显然比单纯通过节点id来决定存活节点更加合理。

在Bug 29062169中,Oracle研发详细讨论了这个问题发生的根本原因。队列计算代码(clssnmsetcohort) 没有能够区分出dead节点和alive节点,由于dead节点不会更新磁盘心跳因此使用了旧的位图信息,其中包含了所有节点成员的状态位;而alive节点更新了最新的位图,将deat节点状态设置为关闭状态。因此dead节点的状态位包含的节点数量反而高于alive节点,最终导致alive节点被踢出集群。针对这个Bug的解决方案是,一旦有节点因为miscount状态达到100%而dead,则直接丢弃掉其状态位图。

Oracle并没有给出这个Bug的补丁,而是随后发布了Bug 30227028的补丁。在这个Bug中更加精细的考虑了节点之间可能因为时间戳的误差导致节点被错误踢出集群的问题。Patch 30227028包含在19.11的OCWRU中,对于19.11以下版本,建议升级到19.11以上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值