尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Oracle 19c RAC节点恢复实战:从节点驱逐到重新加入集群完整指南

Oracle 19c RAC节点恢复实战:从节点驱逐到重新加入集群完整指南 1. 事故现场节点2是如何失联的凌晨两点四十分手机上的监控告警把我从睡梦中拽起来rac2.example.com: Oracle Clusterware resource offline。打开电脑连上跳板机crsctl status resource -t刷出来一片红色——节点2上的所有资源全部变成OFFLINEscan listener也把节点2摘掉了。第一反应是心跳网络闪断但ping 192.168.20.12能通SSH能连上说明私网没问题。真正让我心里一沉的是登录到节点2之后查/var/log/messages一堆SCSI层的IO错误刷屏紧跟着是内核panic。这台机器挂的是本地系统盘从报错特征看盘上已经有坏道了系统盘读不出来了。也就是说这不是一次重启一下就能恢复的故障节点2需要重装操作系统然后再一步一步把它加回RAC集群。这种场景在Oracle 19c RAC生产环境里属于标准的节点恢复流程但很少有人在真正出故障之前完整演练过。RAC的高可用性此时已经降级成单节点运行节点1承载全部业务流量风险极高。而恢复节点2这件事说起来就一句话真正操作起来涉及节点驱逐、系统重装、GI软件加入、数据库实例重新注册四段流程环环相扣哪一段掉链子都得从头排查。这也是我写下这篇文章的原因把这次生产环境下Oracle 19c RAC恢复节点2的完整过程、操作命令、踩过的坑原原本本记录下来。如果你也是DBA或者正在维护Oracle RAC环境这篇文章能帮你节省至少一个通宵的排查时间。先用一个表格把本次故障的环境信息固定下来后面所有操作都基于这个环境项目值集群节点rac1正常、rac2本次恢复目标数据库版本Oracle Database 19c19.16Grid Infrastructure版本19c19.16操作系统Oracle Linux 7.9数据库名称ORCLdb_unique_name同为ORCL实例ORCL1、ORCL2共享存储ASM磁盘组 DATA、FRAGI Home/u01/app/19.0.0/gridDB Home/u01/app/oracle/product/19.0.0/dbhome_1Scan IP192.168.10.100Public网络192.168.10.11rac1/ 192.168.10.12rac2Private网络192.168.20.11rac1/ 192.168.20.12rac22. 动手前必须清点的家底备份、集群资源与停机窗口恢复节点2不是上来就重装系统的。生产环境里任何操作都先要回答三个问题如果中途失败了能不能回滚当前集群还能不能撑住我需要多长的时间窗口2.1 确认RMAN备份可用性是第一优先级节点2的系统盘虽然坏了但RAC共享存储上的数据并没有损坏节点2本地Oracle软件和数据文件都是共享存储上的。不过理论上应该没坏和确认过没坏是两回事。我做的第一件事是在节点1上执行rman target / catalog rcatowner/xxxcatalog RMAN list backup of database; RMAN restore database preview;restore database preview这一步非常关键它会把恢复数据库需要的所有备份片和归档日志路径全部验证一遍。如果连这份备份都是残缺的节点2的恢复就得上升到数据恢复层面那就完全不是本文的讨论范围了。确认无误后我还手动做了一次控制文件备份RMAN backup current controlfile format /backup/control_%U.bak;这个动作是为了防止我们在折腾过程中控制文件意外损坏多一道保险。2.2 盘点集群中元数据的健康状态RAC集群的元数据主要存在三处OCROracle Cluster Registry、表决盘Voting Disk、以及GI的GPNP profile。OCR相当于集群的大脑记忆表决盘负责节点分裂时投票选主。Oracle 19c默认把OCR和Voting Disk都放在ASM磁盘组里所以只要ASM磁盘组是好的这些元数据就还在。在节点1上执行ocrcheck输出类似Status of Oracle Cluster Registry is as follows : Version : 3 Total space (kbytes) : 416040 Used space (kbytes) : 1356 Available space (kbytes) : 414684 ID : 123456789 Device/File Name : DATA Device/File integrity check succeededDevice integrity check succeeded说明OCR没问题。接着检查voting diskcrsctl query css votedisk## STATE File Universal Id File Name Disk group -- ----- ----------------- --------- --------- 1. ONLINE 1234567890abcdef... DATA DATA 2. ONLINE 1234567890abcdef... DATA DATA 3. ONLINE 1234567890abcdef... DATA DATA Located 3 voting disk(s).3个voting disk全部ONLINE。这两个检查通过意味着节点2加回集群后集群层面的元数据不需要重建只需要把新节点注册进来。2.3 明确恢复的真实含义重建GI与数据库实例这里必须澄清一个概念RAC节点恢复恢复的不是数据文件而是节点本身的服务能力。数据库的数据文件、控制文件、联机日志都在共享存储ASM里节点2崩溃期间节点1上的实例ORCL1会接管全部数据库工作并针对节点2已经提交但尚未写盘的事务执行实例恢复Instance Recovery这个动作由Oracle自动完成。所以节点2重装后要做的事情是重新安装Grid Infrastructure软件让节点2能入群在DB Home中重新配置数据库软件把实例ORCL2注册回集群并启动验证业务流量正常。2.4 申请窗口与风险评估节点2恢复过程中节点1持续承担业务原则上不需要停业务。但GI的add node操作、root.sh执行期间集群会有短暂重新配置的过程保险起见我和业务方沟通了一个2小时的维护窗口时间定在凌晨3点到5点。同时有一个不可忽视的风险如果节点1在节点2恢复期间也出问题整个数据库就真的单点运行了。我把这个风险明确写进了操作方案里并准备好了备用的连接串确保一旦出现极端情况能第一时间联系厂商支持。3. 把节点2从集群中安全驱逐先摘除再治疗生产环境的经验告诉我不要在一个半死不活的节点存在时直接重装。节点2虽然系统崩了但如果它的网络还在、或者重启后短暂恢复了部分进程集群里就会有各种残留幻想——比如CSSD还在等待节点2的心跳crsd还在尝试拉起节点2上的资源。所以首要任务是把这个节点从集群中正式驱逐让控制层彻底转移。3.1 evict node让集群不再等待节点2在节点1上执行crsctl evict node rac2 -f-f是强制驱逐不需要节点2在线响应。这个命令的效果是让CSSDCluster Synchronization Service Daemon立即把节点2从集群成员中移除不再计算它的心跳超时。执行后看一眼状态crsctl status resource -t此时rac2下的所有资源应该都不再显示或者显示为UNKNOWN/N/A而原来由节点2承载的scan listener、资源等已经自动failover到节点1。3.2 清理集群中的节点残留信息驱逐不等于删除配置。必须检查一下olsnodes里节点2的记录olsnodes -s -t如果rac2的状态显示为UNKNOWN或已不在列表里就可以跳过删除操作如果还显示ONLINE之类的状态这种情况在强制驱逐后可能短暂存在需要用下面两条命令彻底清理节点记录crsctl delete node -n rac2这个命令会把节点2从OCR的节点列表中摘除。注意crsctl delete node必须在节点2完全不可达的情况下执行否则会报错。执行完再确认olsnodes -s -t正常情况下输出里就只剩 rac1 了。这个步骤很多人觉得多余但实际工作中我见过不止一次节点重装后add node时因为OCR里还保留着旧节点的token信息导致GPNP profile分发失败配置一直卡在33%或者45%的位置。先把它彻底清理干净后面会省很多事。3.3 备份节点2残留的配置目录虽然系统盘坏了但如果能通过救援模式挂载还是建议把节点2上一些关键配置备份下来再动系统——比如/etc/oracle/、/etc/oraInst.loc、/u01/app/oraInventory。这些目录在重装系统后会全部丢失但其中一些信息比如inventory location会在GI add node时需要确认。我这次运气还行系统盘虽然报错但还勉强能挂载我挽救出了/etc/oracle/ocr.loc。后来实际安装GI时发现好在这份文件被清理干净了否则可能影响oraInventory的识别。经验补充如果是静默安装GI建议提前把旧的/etc/oracle/ocr.loc和/etc/oraInst.loc删除避免新安装时读取到无效路径。3.4 记录节点1的基线信息重装节点2之后所有环境配置必须和节点1保持完全一致否则加入集群时会报node mismatch之类的错误。在这里强烈建议趁节点1还健康先把它关键配置记录下来# 用户和组信息 id grid id oracle # Grid和Oracle用户的UID/GID rpm -qa | grep oracleasm# 网络配置 ip addr show cat /etc/hosts cat /etc/resolv.conf # 时间同步 chronyc sources -v# ASM磁盘udev规则 cat /etc/udev/rules.d/99-oracle-asm.rules把这些信息截图归档重装系统时直接照抄。特别是grid/oracle用户的UID和GID必须与节点1一致否则共享存储的权限识别会出问题这在后面ASM磁盘访问时是致命的。4. 重装GI并让节点2重新入群的关键操作系统重装完成后接下来的核心工作分两个阶段先做环境基础配置再执行GI的add node。这个阶段坑最多我不只在自己环境里踩过也见过不少同事在这里翻车。4.1 系统层面的配置比安装本身更重要重装完Oracle Linux 7.9后我完全没有急着装GI而是先把以下基础项逐条对齐用户与组节点1上grid和oracle用户的组信息需要保持一致。我用节点1的id grid、id oracle输出作为唯一标准groupadd -g 54321 oinstall groupadd -g 54322 dba groupadd -g 54323 oper groupadd -g 54324 backupdba groupadd -g 54325 dgdba groupadd -g 54326 kmdba groupadd -g 54327 asmdba groupadd -g 54328 asmoper groupadd -g 54329 asmadmin useradd -u 54321 -g oinstall -G dba,oper,backupdba,dgdba,kmdba,asmdba grid useradd -u 54322 -g oinstall -G dba,oper,backupdba,dgdba,kmdba oracle目录规划GI Home和DB Home路径与节点1完全一致避免后续脚本识别错乱mkdir -p /u01/app/19.0.0/grid mkdir -p /u01/app/oracle/product/19.0.0/dbhome_1 chown -R grid:oinstall /u01/app/19.0.0 chown -R oracle:oinstall /u01/app/oracle chmod -R 775 /u01/app网络与主机名解析/etc/hosts中必须把两个节点的public IP、private IP、scan IP都写进去注意scan IP必须在DNS或hosts中有正向解析。19c的GNS配置虽然可以动态管理scan但很多人还是用传统DNS方式那就必须保证192.168.10.11 rac1.example.com rac1 192.168.10.12 rac2.example.com rac2 192.168.10.100 scan-cluster.example.com scan-cluster 192.168.20.11 rac1-priv.example.com rac1-priv 192.168.20.12 rac2-priv.example.com rac2-priv时间同步RAC对节点间时间偏差容忍度很低19c的集群心跳对时钟偏差尤其敏感。这次我直接用chrony向同一个NTP服务器同步systemctl enable chronyd systemctl start chronyd chronyc makestep chronyc sources -v确保节点1和节点2的时间差在100毫秒以内。有个容易被忽略的细节/etc/chrony.conf里默认的makestep策略是只在启动时校准对于长期运行的数据库服务器建议加上makestep 1 3systemctl restart chronyd这个配置能让chronyd在每次同步时如果偏差超过1秒就直接跳变避免累积漂移。共享存储与ASM磁盘权限节点2要能识别ASM磁盘。如果是使用udev管理ASM磁盘按照节点1的规则文件内容照抄cat /etc/udev/rules.d/99-oracle-asm.rules EOF KERNELsdb, OWNERgrid, GROUPasmadmin, MODE0660 KERNELsdc, OWNERgrid, GROUPasmadmin, MODE0660 EOF然后刷新udev规则udevadm control --reload-rules udevadm trigger重装后盘符可能发生变化务必用lsblk和oracleasm listdisks如果用ASMLib逐一确认设备对应关系不要想当然认为sdb还是刚才那块盘。这一步如果搞错后面GI安装时ASM磁盘组会找不到报ORA-15032之类的错。4.2 GI软件安装add node的静默流程环境准备完成后正式开始把节点2加入GI集群。Oracle 19c的Grid Infrastructure支持在线添加节点一般操作是在**现有节点rac1**上运行gridSetup.sh选择添加节点然后按提示把响应文件复制到新节点执行。为了可复现性这里以静默方式为例。先在 rac1 上用grid用户执行cd /u01/app/19.0.0/grid ./gridSetup.sh -addNode -silent -nodeList rac2 -ignoreDownNodes-ignoreDownNodes这个参数很关键它告诉安装程序忽略当前不在集群里的节点。如果没有它会报错说节点rac2状态异常。执行过程中会自动生成响应文件通常在/u01/app/19.0.0/grid/cfgtoollogs/addNode_rac2.rsp。把它拷贝到节点2scp /u01/app/19.0.0/grid/cfgtoollogs/addNode_rac2.rsp rac2:/tmp/然后在节点2上用grid用户执行cd /u01/app/19.0.0/grid ./gridSetup.sh -silent -responseFile /tmp/addNode_rac2.rsp -executeConfigTools这个阶段会执行一系列配置操作包括GPNP profile同步、OCR注册、网络配置等。正常情况下跑完后会提示在节点2上以root执行$ORACLE_HOME/root.shid cd /u01/app/19.0.0/grid sh root.shroot.sh是这次恢复中最容易出问题的环节。执行过程会自动启动OHASD并尝试把节点2加入集群。如果一切顺利脚本最后会输出一堆CRS-2672: Attempting to start...等信息并提示节点已加入集群。4.3 root.sh执行失败的两个典型场景第一次执行root.sh的时候我在60%左右的位置卡住了日志里报CRS-5017: The cluster command create failed. CRS-5044: The cluster node is down.原因很快就定位到ASM磁盘权限不对。系统重装后udev规则里指定的设备名sdb/sdc和新环境不对应导致grid用户无法访问磁盘组。解决方法是修正udev规则后重新刷盘名然后把root.sh重新执行一次即可。注意root.sh在失败后重跑是安全的不需要卸载GI。第二个坑来自hostname解析。节点2的/etc/hosts里居然还带了一行旧的IP映射导致集群通信解析到错误地址。检查方法是grep -E rac2|scan /etc/hosts清理干净重启网络服务后root.sh顺利跑完。4.4 集群状态验证root.sh完成后第一时间确认集群整体状态crsctl status resource -t olsnodes -s -t cluvfy stage -post nodeadd -n rac1,rac2olsnodes -s -t的输出应该显示rac1 ONLINE Online rac2 ONLINE Online如果看到 rac2 是UNKNOWN大概率是GPNP profile还没同步等待几分钟再执行crsctl get clusterpnp排查。5. 数据库实例回归从实例注册到业务连接验证集群层通了接下来就是把ORCL2实例加回数据库资源并启动。这一步相对从容但依然有细节要注意。5.1 数据库软件安装先安装数据库软件到 DB Home。在节点2上解压数据库安装包以oracle用户执行cd /u01/app/oracle/product/19.0.0/dbhome_1 ./runInstaller -silent -responseFile /u01/app/oracle/db_install.rsp -ignorePrereqFailure关键参数要保证INGRID所有者正确ORACLE_HOME路径与节点1一致。安装完成后以root执行root.shDB Home的root.sh。其实如果节点1的DB Home还在可以考虑直接把节点1的DB Home打包复制到节点2能省不少编译时间。但为了环境的纯净性和后续补丁管理我这次选择了完整安装时间上多花10来分钟但放心。5.2 注册实例srvctl add instance数据库本身通过共享存储已经在集群里注册了数据库资源但节点2的实例ORCL2还没有绑定进这个资源定义里。需要在节点1上用grid用户或oracle用户执行srvctl add instance -db ORCL -instance ORCL2 -node rac2执行完检查数据库资源配置srvctl config database -d ORCL -verbose输出里应该看到两个实例节点信息Datbase name: ORCL Database unique name: ORCL Database instances: ORCL1, ORCL2 Configured nodes: rac1,rac25.3 启动实例并观察alert日志然后启动节点2实例srvctl start instance -db ORCL -instance ORCL2启动过程中立刻去看ORCL2的alert日志tail -f /u01/app/oracle/diag/rdbms/orcl/ORCL2/trace/alert_ORCL2.log由于节点2是正常形式重新加入启动时会经历实例恢复阶段介质恢复或实例恢复alert日志里会出现类似Recovery of Online Redo Log Thread 2 for seq# ...这是正常现象说明Oracle在应用节点2崩溃前留下的redo日志保证数据一致性。等出现Completed: ALTER DATABASE OPEN后实例已经open。再用集群工具确认srvctl status database -d ORCL输出应显示Instance ORCL1 is running on node rac1 Instance ORCL2 is running on node rac25.4 监听与服务资源检查19c RAC的监听由GI统一管理。节点2上检查监听状态lsnrctl status LISTENERcrsctl stat res ora.LISTENER.lsnr -tscan listener是集群级的节点2只要被加入集群scan服务会在节点间自动均衡不需要额外修改。但要注意检查数据库的service是否正确注册到了节点2lsnrctl services LISTENER正常情况下能看到orcl.orcl的相关服务监听在NAMES里确认ORCL2实例的主service已注册。5.5 业务验证不能只看实例状态集群和数据库都起来了不代表业务就真的恢复了。我做了以下几层验证先用SQL检查一下会话能否连接sqlplus system/xxxorcl SQL select instance_name, status from gv$instance;再用JDBC短连接测试jdbc:oracle:thin://scan-cluster.example.com:1521/orcl最后盯一张核心业务表的最近数据写入情况确认应用具备正常读写能力。如果业务方有连接池需要确认连接池配置里FAILEOVER的节点列表是否已包含新节点。6. 恢复后的体检与这次事故留下的几条教训节点2回到集群并不等于收工真正的收尾是全面的健康体检和复盘。我按下面的顺序逐一过了一遍。6.1 静态体检清单# 集群成员 olsnodes -s -t # 集群资源 crsctl status resource -t # 数据库状态 srvctl status database -d ORCL # ASM磁盘组 asmcmd lsdg # 集群健康检查 cluvfy stage -post nodeadd -n rac1,rac2# 检查OCR备份是否正常 ocrconfig -showbackup# 检查最近一次RMAN备份连续成功 rman target / EOF list backup summary; EOF同时检查节点2的历史告警日志里有没有ORA-600、ORA-07445之类的意外报错。另外把节点2加入后的数据库性能基线记录下来AWR报告看过一次节点2的负载确认服务质量和节点1对齐。6.2 一套值得固化的节点重装runbook这次恢复最大的收获不是成功把节点2拉起来了而是把整个流程标准化成了一份runbook。以后再有类似故障照着走一遍就行阶段核心动作验证命令故障识别确认节点失联原因crsctl status resource -t备份确认验证RMAN可用性restore database preview节点驱逐evict并清理旧节点记录crsctl evict node、crsctl delete node系统准备用户/网络/时间/存储配置id、ip addr、chronyc、lsblkGI加入gridSetup.sh -addNode root.sholsnodes -s -t实例加入srvctl add instance并启动srvctl status database业务验证连接测试与服务检查sqlplus、lsnrctl services体检集群与数据库全面检查cluvfy、ocrconfig、srvctl status6.3 几条从这次事故里提炼的教训第一OCR和voting disk的备份绝不能依赖反正都在ASM里这个假设。虽然这次OCR和表决盘都存活但我见过OCR存储在本地磁盘上的环境节点坏了OCR也就没了。对于19c环境定期执行ocrconfig -export /backup/ocr_$(date %Y%m%d).bak是值得纳入备份脚本的动作。第二节点重装里90%的问题出在环境一致性上UID/GID不一致、udev规则失效、hosts解析错误、时间偏差过大。这些看起来是小问题却会让GI安装阶段就卡住而且报出的错误信息往往不直接指向根因。建议在节点1健康时就把这些配置信息导出存档而不是出了故障才临时去翻。我自己现在就维护了一个/etc/oracle/rac_env.txt记录所有关键环境参数每次节点变更后自动更新。第三不要吝啬监控。这次故障如果在早期被识别到磁盘S.M.A.R.T.异常完全可以在业务低峰期主动重装而不是在凌晨被告警吵醒。我现在给所有RAC节点加了磁盘健康监测和集群心跳时延监控阈值一到就提前介入。第四演练的价值不可替代。经历过这次之后我在测试环境完整跑了一遍同样的恢复流程把add node和srvctl add instance的具体参数都验证过。真到生产环境再做类似操作心里就有底得多。如果你所在的公司有条件强烈建议在测试机房每个月做一次节点模拟故障演练哪怕只是验证一下runbook里的命令能跑通都会让你在真正出事时冷静得多。这次恢复折腾下来我的最大感受是节点恢复本身并不复杂复杂的是在凌晨、在业务压力下、在节点1随时可能也挂掉的心理阴影中还能一步步冷静地把命令执行完。把自己平时积累的检查清单、环境台账、命令手册用好灾难恢复就真的只是一次标准化操作。
返回列表