1. 这套“简单”到底简单在哪
Oracle 23ai RAC 部署这件事,我第一次听到“简单”两个字时是持怀疑态度的。毕竟从 10g 时代一路做过来,两节点 RAC 的全流程我闭着眼都能背:核对 OS 版本、改内核参数、配 hosts、划共享盘、装 GI、跑 root.sh、装 DB 软件、DBCA 建库、配 SCAN、加服务、验切换……整套下来,顺利的话大半天,遇到私网丢包或者 ASM 盘识别不到,两天都出不来。所以当有人告诉我 23ai 的 RAC 能“很简单”地搭起来时,我第一反应是:是不是把哪一步偷偷省了。
真上手做了三轮之后,结论是:RAC 该有的复杂度一点没少,变的是“把复杂度收敛到哪里”。过去的做法是把 12 个手工步骤摊在时间线上,每步都可能出错,且出错点和出错原因隔得很远;现在这套做法是把它们压进三个响应文件加几条校验命令里,出错点集中、可回溯、可重跑。换句话说,这条标题里说的“简单”是方法论层面的简化——先想清楚,再一次性配置,最后一次性校验,并非版本本身的额外功能。
这篇内容写给谁:如果你已经知道 RAC 是什么、装过一次 19c 或者更早版本,现在要迁移到 23ai,或者要给团队搭一套标准的部署模板,那这篇可以直接拿去用;如果你是刚接触 RAC 的新手,建议你先在虚拟化环境里按本文走一遍,再考虑上生产。文中所有主机名、IP、目录都是虚构的示例代称,你按自己环境替换;涉及具体版本补丁的行为差异,最终以你手上介质对应的官方文档为准。
1.1 传统 RAC 部署到底卡在哪里
先说清楚老流程的毛病,才知道新做法在治什么病。我梳理了一遍过往的 RAC 部署记录,真正卡住人的无非六处:
- 操作顺序不稳定:先配内核参数还是先建用户组、先划盘还是先装 preinstall,顺序错了会留下互相覆盖的配置,最典型的是先手工改了
sysctl.conf再装 preinstall 包,结果被包里的配置覆盖回去,重启后参数又不对了。 - 手工操作不可复现:每台机器的私网网卡名不一样(
ens192、eth1、enp4s0f0全见过),每次都要现查,响应文件里的网卡名字段一填错,GI 装到一半报错回滚。 - 共享存储权限漂移:
/dev/sdb这种名字重启一次可能就变了,udev 规则没写对,GI 起来的瞬间 ASM 找不到盘,ORA-15018报出来,排查得从头开始。 - 节点间时间与网络不一致:两节点 chrony 没对好,CRS 起不来;私网 MTU 不一致,心跳包被丢,节点被踢出去,日志里只有一行 EVMD 报错。
- root.sh 时机模糊:node1 跑完 root.sh 要不要等 node2,两边谁先谁后,老文档里五花八门,实际上顺序错了会导致 OCR 写坏。
- 建库参数靠猜:DBCA 图形界面一路下一步,建完才发现字符集不对、redo 太小、归档没开,返工代价极高。
这六条共同点是:它们都属于“一次性决策”,做对了后面一路顺,做错了后面全是排查。所以真正该做的是把一次性决策提前定死,再用脚本固化。
1.2 我把流程压成了三段式
我的做法是把整件事拆成三段,每段有独立的输入和输出,段与段之间用校验点隔开:
| 阶段 | 输入 | 输出 | 校验方式 |
|---|---|---|---|
| 第一段:系统层 | 主机清单、磁盘清单、IP 规划 | 两节点 OS 一致、盘符固化、用户组齐全 | cluvfy stage -pre crsinst |
| 第二段:集群层 | grid 响应文件 | GI 起来、ASM 磁盘组可挂 | crsctl check cluster -all |
| 第三段:数据库层 | db 响应文件 + DBCA 参数 | RAC 实例双活、SCAN 可连 | gv$instance双行、切换测试 |
这个三段式的好处很直接:任何一段失败,你只需要退回这一段的起点,不用从头再来。GI 装坏了,清掉后用同样的响应文件重跑;建库失败,删库重建不碰集群。过去那种“一路装到底、坏了全推倒”的痛苦,主要是没有分段校验点。
注意:23ai 的 Grid Infrastructure 与 Database 是两个独立介质、独立 Home。不要图省事把两者装到同一个 ORACLE_HOME,这个在 RAC 场景下一定会出问题,属于经典的坑,踩了会浪费你半天时间。
2. 上机前的规划表:一次定死资源和目录
我见过太多人跳过这一步,然后卡在“SCAN 用几个 IP”“ASM 要不要拆两个盘组”“OCR 放哪里”上反复试。规划做细一点,后面能省掉一整天的试错。下面这套取值是我在虚拟化环境下验证过的,物理机按比例放大即可。
2.1 主机、内存与存储的实测取值
我的测试环境是两台 16 核 / 64G 内存的虚机,配一块可共享的块存储。这套配置能跑起来,但生产环境不要照抄,尤其是内存。
内存怎么算。RAC 是每节点跑一个实例,所以内存按单节点算,不要按总量除。以 64G 为例:操作系统 + Grid Infrastructure + ASM 实例 + 监控代理留 14G,剩 50G 给数据库实例。这 50G 里,SGA 给 24G,PGA 给 12G,留 14G 余量应对峰值,剩下 14G 其实是防御性冗余——不要把内存挤满,RAC 节点因为内存抖动导致 ASM 实例被 OOM 杀掉,整个节点就掉线了,这个代价远大于多买两条内存。
SGA 与 HugePages 的关系。RAC 下不能用自动内存管理(AMM),memory_target在集群环境下根本不支持,只能用自动共享内存管理(ASMM)。用了 ASMM 就应该配 HugePages,否则 24G 的 SGA 会被切成几十万个小页,TLB 命中率低得可怜。计算方式很朴素:
nr_hugepages = SGA 大小(MB) / 2 + 10% 余量 24G => 24 * 1024 / 2 = 12288,加余量取 13312两台机器在sysctl.conf里写vm.nr_hugepages = 13312,数据库参数配use_large_pages=ONLY。这里有个细节:一旦设成ONLY,如果大页不够,实例直接起不来,报ORA-27102。所以宁可多给 1024 个页,也不要刚刚好。
存储怎么划。我把共享盘分成两组:
| 磁盘组 | 用途 | 盘数与大小 | 冗余方式 | AU 大小 |
|---|---|---|---|---|
| CRS | OCR + Voting Disk | 3 块 8G | NORMAL(生产)/ EXTERNAL(测试) | 4M |
| DATA | 数据文件 | 4 块 100G | NORMAL | 4M |
| RECO | 归档日志 | 2 块 100G | NORMAL | 4M |
OCR 和 Vote 一定要单独放,不要和数据文件挤在同一个盘组。理由很实际:数据盘组被打满导致 OCR 写不进去,整个集群会失去一致性保护,然后节点重启,这种事我见过两次,修起来非常难受。
2.2 网络规划:公网、私网、SCAN 的分配顺序
网络是 RAC 里最容易配错、也最难排查的部分。我的规划习惯是先画表再动手:
| 角色 | 举例地址 | 说明 |
|---|---|---|
| 公网 VIP(node1 / node2) | 192.168.56.11 / .12 | 客户端与运维入口,故障时漂移 |
| 物理公网 IP | 192.168.56.21 / .22 | 主机固定地址,不能漂 |
| 私网(心跳 + ASM) | 10.0.0.21 / .22 | 建议独立网卡,不走路由 |
| SCAN VIP | 192.168.56.31 / .32 / .33 | 三个地址对应三个 SCAN Listener |
| SCAN 名称 | rac-scan | 必须在 DNS 或三节点 hosts 里解析到三个 IP |
几个常被忽略的点:
- SCAN 用三个 IP 是上限,不是必须。测试环境一个也能跑,但生产建议三个,客户端连接分配更均匀,某个 Listener 挂掉影响面小。
- 私网必须和公网不同网段,且两节点私网在同一网段。这不是“建议”,是硬性要求,跨网段的私网会让 HAIP 起不来。
- HAIP 是自动的。23ai 里集群互联的高可用地址(
169.254.x.x段)由集群自己管,不需要你手工配,但防火墙策略要放行这个网段,否则心跳不通。测试环境最省事的做法是直接关掉防火墙,生产环境则要精确放行。 - MTU 两节点必须一致。公网 1500、私网 9000 是可以的(只要两边一致),但如果 node1 私网 9000、node2 私网 1500,装机前置检查会直接报 MTU 不一致,这个错误信息很明确,照着改就行。
提示:所有主机名、IP、SCAN 名称在动手前先写进两节点的
/etc/hosts,格式为“IP 主机名 主机名-域名后缀”。RAC 对主机名解析非常敏感,hostname -f返回短名会导致后续节点添加失败。
2.3 目录结构与用户组:装完再改是灾难
目录规划的原则是:同一个路径在两节点上必须完全一致,且属于同一套用户组。我用的结构:
/u01/app/oraInventory 库存目录,属主 oinstall /u01/app/grid GI 的 ORACLE_BASE /u01/app/23ai/grid GI 的 ORACLE_HOME /u01/app/oracle DB 的 ORACLE_BASE /u01/app/23ai/db DB 的 ORACLE_HOME用户组我用了标准六件套:oinstall(主组)、dba(OSDBA)、oper(OSOPER)、backupdba、dgdba、kmdba、racdba。有人图省事只建oinstall+dba,能装能跑,但后面做 RMQ 备份、Data Guard、TDE 加密时会发现权限对不上,需要重新授权甚至重装 Home。这一步多花十分钟,后面省几小时。
还有两个容易踩的细节:
- grid 用户和 oracle 用户的 UID / GID 在两节点上必须完全一致。不一致的情况下,共享存储在两边看到的属主不同,ASM 会认为盘不可用。用
id grid、id oracle两边对一遍,数字对不上就改。 - 不要给 oracle / grid 用户配免密登录 root。这对部署没有任何帮助,反而会让后续的安全基线检查不过。
3. 系统层准备:准备工作交给预安装包完成
这一步是整篇内容里“简化”感最明显的地方。以前要手工改十几处内核参数、核对一堆 rpm 包、写 limits,现在一个预安装包基本全覆盖。
3.1 预安装包和内核参数的落地方式
两节点都执行:
# 关闭透明大页与 NUMA 均衡,避免内存抖动 echo never > /sys/kernel/mm/transparent_hugepage/enabled echo never > /sys/kernel/mm/transparent_hugepage/defrag # 预安装包会把依赖、sysctl、limits、用户组一次性写好 dnf install -y oracle-database-preinstall-23ai # 按自己的规划覆盖关键内核参数 cat >> /etc/sysctl.d/99-oracle-rac.conf <<'EOF' kernel.shmmni = 4096 kernel.sem = 250 32000 100 128 fs.file-max = 6815744 fs.aio-max-nr = 1048576 net.ipv4.ip_local_port_range = 9000 65500 net.core.rmem_default = 262144 net.core.rmem_max = 4194304 net.core.wmem_default = 262144 net.core.wmem_max = 1048576 vm.nr_hugepages = 13312 vm.swappiness = 10 EOF sysctl --system这里有个我反复验证过的顺序问题:预安装包必须在写自定义 sysctl 之前装,因为包会写入自己的/usr/lib/sysctl.d/配置文件,优先级比/etc/sysctl.d/低。如果你先写自定义配置再装包,覆盖关系虽然是自定义的赢,但包可能顺带调整了limits.conf和 PAM,容易造成理解混乱。统一用“先装包、再覆盖”的顺序,两节点的最终配置可以用sysctl -a | grep -E 'shmmni|sem|nr_hugepages'比对,输出必须一模一样。
limits.conf我也习惯显式覆盖一遍,不依赖包的默认值:
grid soft nofile 1024 grid hard nofile 65536 grid soft nproc 16384 grid hard nproc 16384 grid soft stack 10240 oracle soft nofile 1024 oracle hard nofile 65536 oracle soft nproc 16384 oracle hard nproc 16384 oracle soft stack 10240验收方式很简单:su - grid -c "ulimit -n"和su - oracle -c "ulimit -n",两节点输出应该都是 65536。如果还是 1024,说明 PAM 没生效或者被别的配置覆盖了,通常是/etc/security/limits.d/下有更高优先级的文件,检查一下文件名排序。
3.2 共享盘识别与设备权限固化
共享盘这一步是 RAC 部署里唯一没法完全自动化的环节,因为它依赖你的存储环境。核心目标只有一个:让同一个盘在两节点上永远指向同一个设备名,并且属主属组固定。
我用 udev 规则解决。先看盘的唯一标识:
# 逐块查 SCSI ID,确认两节点看到的是同一批盘 for d in /dev/sd{b,c,d,e,f,g}; do echo -n "$d -> " /usr/lib/udev/scsi_id -g -u -d $d done拿到 ID 后写规则,示例(实际 ID 换成你自己的):
KERNEL=="sd*", SUBSYSTEM=="block", PROGRAM=="/usr/lib/udev/scsi_id -g -u -d /dev/$name", RESULT=="3600a098038304a4b2b4b4a7a7a7a7a7", SYMLINK+="asm-crs1", OWNER="grid", GROUP="asmadmin", MODE="0660" KERNEL=="sd*", SUBSYSTEM=="block", PROGRAM=="/usr/lib/udev/scsi_id -g -u -d /dev/$name", RESULT=="3600a098038304a4b2b4b4a7a7a7a7a7b", SYMLINK+="asm-data1", OWNER="grid", GROUP="asmadmin", MODE="0660"然后udevadm control --reload-rules && udevadm trigger --type=devices --action=change,检查:
ls -l /dev/asm-* # 两节点输出应完全一致,权限 crw-rw---- grid asmadmin注意:刻盘前把每块盘的头部清一下(
dd if=/dev/zero of=/dev/sdX bs=1M count=100),残留的分区表或旧 ASM 头会让 GI 拒绝使用这块盘,报错信息通常只说“磁盘不可用”,不告诉你为什么。
此外,两节点必须关掉同一批服务,别只关一台:
systemctl disable --now firewalld systemctl disable --now NetworkManager # 静态 IP 场景下更稳 sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config提示:
firewalld关掉只是测试环境的省事做法。生产环境保留防火墙的话,必须放行公网段、私网段、HAIP 段(169.254.0.0/16)以及 SCAN 端口,缺一个就会卡在节点添加或者 SCAN 监听起不来。
4. Grid Infrastructure 安装:响应文件静默跑通
到这一步,前面的准备工作如果做扎实了,整个安装过程就是“执行一条命令 + 等”。这一节我重点拆响应文件,因为它是整个流程里唯一需要动脑的地方。
4.1 响应文件逐段拆解
我的 grid 响应文件内容(路径和主机名替换成你自己的):
oracle.install.responseFileVersion=/oracle/install/rspfmt_crsinstall_response_schema_v23.0.0 ORACLE_HOSTNAME=rac1 UNIX_GROUP_NAME=oinstall INVENTORY_LOCATION=/u01/app/oraInventory SELECTED_LANGUAGES=en,zh_CN ORACLE_HOME=/u01/app/23ai/grid ORACLE_BASE=/u01/app/grid oracle.install.option=CRS_CONFIG oracle.install.asm.OSDBA=asmdba oracle.install.asm.OSOPER=asmoper oracle.install.asm.OSASM=asmadmin oracle.install.crs.config.clusterName=rac-cluster oracle.install.crs.config.ClusterType=STANDARD oracle.install.crs.config.clusterNodes=rac1:rac1-vip:HUB,rac2:rac2-vip:HUB oracle.install.crs.config.networkInterfaceList=ens192:192.168.56.0:1,ens224:10.0.0.0:5 oracle.install.crs.config.scanType=LOCAL_SCAN oracle.install.crs.config.gpnp.scanName=rac-scan oracle.install.crs.config.gpnp.scanPort=1521 oracle.install.crs.config.useIPMI=false oracle.install.crs.config.storageOption=FLEX_ASM_STORAGE oracle.install.asm.diskGroup.name=CRS oracle.install.asm.diskGroup.redundancy=EXTERNAL oracle.install.asm.diskGroup.AUSize=4 oracle.install.asm.diskGroup.disks=/dev/asm-crs1 oracle.install.asm.diskGroup.diskDiscoveryString=/dev/asm-* oracle.install.asm.monitorPassword=Monitor#2024 oracle.install.asm.SYSASMPassword=Sysasm#2024几个字段值得单独说明,填错概率最高:
clusterNodes的格式是“主机名:VIP 名:角色”,角色写HUB表示普通节点。这个字段里出现的所有名字都必须在两节点 hosts 里有解析,否则安装程序会在预检查阶段就退出。networkInterfaceList的格式是“网卡名:网段:类型码”,类型码1是公网、5是私网(心跳兼 ASM 用)。网卡名必须和你环境里ip a看到的一致,写错了直接报“接口不存在”。storageOption我选FLEX_ASM_STORAGE,这是推荐值,后续扩容和加盘都更灵活。diskGroup.disks建议只显式写 CRS 需要的盘,其余盘通过diskDiscoveryString让 ASM 自己发现,避免误把系统盘划进磁盘组。- 密码字段要满足复杂度,至少 8 位且包含字母、数字、特殊字符。我在这一步被拦过两次,报错信息很含糊,只提示“密码不符合要求”。
4.2 安装执行节奏与 root.sh 的时机
静默安装用grid用户执行:
su - grid cd /u01/app/23ai/grid ./gridSetup.sh -silent -responseFile /home/grid/grid_install.rsp -waitForCompletion看到Successfully Setup Software之后,此时不要继续下一步,先在两节点分别跑 root.sh,顺序是先 rac1 后 rac2:
# rac1 /u01/app/23ai/grid/root.sh # 等 rac1 的 root.sh 完全结束、提示成功后,再到 rac2 /u01/app/23ai/grid/root.sh这个顺序是硬性的。我在早期版本上试过两边同时跑,OCR 写冲突,集群起不来,最后只能清盘重装。root.sh 执行过程中会做几件事:配置集群启动脚本、创建 OCR 和 Vote、启动 CRS。看输出的时候关注最后几行,出现The Cluster Ready Services (CRS) is now configured这类提示才算过。
4.3 装完立刻做的五项验证
装完不验证,等于没装。这五条命令我每次都会跑一遍,几十秒的事,能挡掉后面 80% 的怪问题:
# 1. 两节点集群状态 crsctl check cluster -all # 2. 资源清单,重点看 ora.asm、ora.crsd、ora.cssd 状态 crsctl stat res -t # 3. ASM 磁盘组是否挂上 asmcmd lsdg # 4. OCR 一致性 ocrcheck # 5. SCAN 与监听 srvctl config scan srvctl status scan_listener判断标准:crsctl stat res -t里所有资源都是ONLINE或ONLINE INTERMEDIATE,不能出现INTERMEDIATE卡住超过五分钟的状态;asmcmd lsdg里 CRS 盘组MOUNTED;ocrcheck返回SUCCEEDED。任何一条不对,先别往下走,回查这一节。
注意:如果
crsctl check cluster -all只在 rac1 上返回正常,rac2 无响应,九成是私网不通或者两节点时间相差太大。先ping私网地址,再chronyc sources -v看时间同步,两个都过了再怀疑更深层的原因。
5. 数据库软件与建库:DBCA 一步写成
集群层稳了,剩下的活其实是“装软件 + 建库 + 验连接”,其中真正需要动脑的只有建库参数。
5.1 数据库软件静默安装的差异点
DB 软件的响应文件和 GI 的差别不大,主要是oracle.install.option变成INSTALL_DB_SWONLY,以及要显式声明各个管理组:
oracle.install.responseFileVersion=/oracle/install/rspfmt_dbinstall_response_schema_v23.0.0 oracle.install.option=INSTALL_DB_SWONLY UNIX_GROUP_NAME=oinstall INVENTORY_LOCATION=/u01/app/oraInventory ORACLE_HOME=/u01/app/23ai/db ORACLE_BASE=/u01/app/oracle oracle.install.db.InstallEdition=EE oracle.install.db.OSDBA_GROUP=dba oracle.install.db.OSOPER_GROUP=oper oracle.install.db.OSBACKUPDBA_GROUP=backupdba oracle.install.db.OSDGDBA_GROUP=dgdba oracle.install.db.OSKMDBA_GROUP=kmdba oracle.install.db.OSRACDBA_GROUP=racdba oracle.install.db.rootconfig.executeRootScript=true oracle.install.db.rootconfig.configMethod=ROOT执行:
su - oracle cd /u01/app/23ai/db ./runInstaller -silent -responseFile /home/oracle/db_install.rsp -waitForCompletion两个细节:一是-ignorePrereqFailure尽量别加,前置检查报的警告八成是真问题,比如大页不够、包缺失,加了跳过只是把炸弹埋到建库阶段;二是executeRootScript=true让安装程序自动在两节点跑 root.sh,省一次手工操作,但前提是当前用户有 sudo 或者在 root 下执行,没权限就老实改回 false 手工跑。
5.2 DBCA 建库参数怎么算出来的
建库这块我把参数分成三类:不能改的、要按容量算的、按业务定的。
dbca -silent -createDatabase \ -templateName New_Database.dbt \ -gdbName RACDB -sid RACDB \ -databaseConfigType RAC \ -nodeinfo rac1,rac2 \ -policyManaged false \ -sysPassword 'Sys#2024pass' -systemPassword 'Sys#2024pass' \ -createAsContainerDatabase true -numberOfPDBs 1 -pdbName PDB1 \ -storageType ASM -diskGroupName +DATA \ -datafileDestination '+DATA' \ -recoveryAreaDestination '+RECO' \ -characterSet AL32UTF8 -nationalCharacterSet AL16UTF16 \ -totalMemory 24576 -memoryMgmtType AUTO_SGA \ -redoLogFileSize 1024 \ -databaseType OLTP -emConfiguration NONE \ -responseFile /home/oracle/dbca_create.rsp \ -useWallet false不能改的部分。-databaseConfigType RAC加-nodeinfo是让它建 RAC 库的关键,少了这两个参数会建出单实例库,之后想转 RAC 极其麻烦。-characterSet AL32UTF8也别动,中文环境用别的字符集后面导入导出会出各种乱码问题。
要按容量算的部分。-totalMemory 24576就是前面算的 SGA 24G,注意 DBCA 里这个参数单位是 MB。-redoLogFileSize 1024是我根据日均归档量估的——redo 太小会导致频繁切换,日志切换时会有短暂的性能抖动,我按每小时切换不超过 3 次来定,实测日增归档 80G 左右的库,1024M 的 redo 刚好。
按业务定的部分。-createAsContainerDatabase true建议开,多租户是 23ai 的默认形态,后面插拔 PDB 做迁移、做测试库非常方便。-emConfiguration NONE是因为我环境里没部署 EM,你要用就改成DBEXPRESS。
密码策略。建库前先确认口令复杂度要求,DBCA 里设的密码会同时作为sys、system的密码,且两节点一致。我在这一步被“密码不符合复杂度策略”卡过一次,报错信息只给一个ORA-28003,其实是 profile 里的校验函数没满足。
5.3 建库后的连通性与切换验证
建库成功不代表可用,要验三件事:实例双活、SCAN 连接正常、故障时能切。
# 1. 两个实例都在 srvctl status database -d RACDB # 2. 通过 SCAN 连进去,看实例分布 sqlplus sys/Sys#2024pass@rac-scan:1521/RACDB as sysdba SQL> select inst_id, instance_name, status from gv$instance; SQL> select name, value from gv$parameter where name = 'cluster_database';gv$instance应该返回两行,cluster_database为TRUE。然后用 SCAN 循环连十次,看实例号是否在两个节点间轮转,轮转说明 SCAN 的负载分发是好的;如果十次全落到同一个节点,检查 SCAN Listener 数量或者客户端连接串是不是写死了地址。
再做一次真实的切换测试(这个步骤我强烈建议在交付前执行):
# 关掉 rac1 上的实例,确认服务漂到 rac2 srvctl stop instance -d RACDB -i RACDB1 srvctl status database -d RACDB # 应用侧通过 SCAN 仍然能连,然后恢复 srvctl start instance -d RACDB -i RACDB1提示:如果业务连接串用的是 SCAN + 服务名,切换时客户端几乎无感;但如果写死了 VIP 或者物理 IP,切换必然中断。上线前务必确认应用侧连接串的正确形态。
服务这块我习惯单独建一个业务服务,而不是让应用连默认的RACDB服务:
srvctl add service -db RACDB -service APPS \ -preferred RACDB1,RACDB2 -policy AUTOMATIC \ -failovertype SESSION -failovermethod BASIC srvctl start service -db RACDB -service APPS这样后续做srvctl relocate service、按服务限流、单独调整服务的并行度都不会影响其他业务。
6. 遇到的问题记录与常见问题速查
前面写得再顺,真机上也一定会遇到问题。我把这几轮遇到的、以及同行反馈过的典型问题整理成表,按报错先定位,别急着重建。
6.1 常见问题速查表
| 现象 / 报错 | 最可能原因 | 处理方向 |
|---|---|---|
| 预检查报 PRVF 类网络错误,提示 MTU 不一致 | 两节点网卡 MTU 或网段配错 | 统一ip link的 MTU,确认私网同网段 |
ORA-15018/ORA-15031磁盘组创建失败 | 盘权限不对 / 盘上有残留头 | 检查/dev/asm-*属主属组,清盘头重试 |
crsctl check cluster只有一台返回正常 | 私网不通或时间不同步 | 先 ping 私网,再看 chrony,最后看 HAIP 状态 |
| root.sh 跑完 CRS 起不来 | 两节点 root.sh 顺序错 / OCR 写冲突 | 查$GRID_HOME/log/<host>/crsd,严重时清盘重来 |
| DBCA 报 ORA-01017 或口令校验失败 | 密码复杂度不满足 | 换含大小写、数字、特殊字符的密码 |
实例启动报ORA-27102 | 大页不足 | 提高vm.nr_hugepages并sysctl -p |
| SCAN VIP 起不来 | hosts / DNS 解析不到三个 IP | 确认nslookup rac-scan返回三条记录 |
| 节点莫名重启,日志含节点驱逐信息 | 私网丢包(虚拟化环境常见) | 检查网卡多队列配置,或明确指定集群互联网卡 |
| 应用连上后偶发断连 | 连接串写死 VIP / 未配服务 | 改为 SCAN + 服务名,配 TAF 参数 |
| 建库后归档空间迅速打满 | redo 过小或归档未设清理策略 | 调大 redo,配 RMAN 归档删除策略 |
这张表覆盖了我实际遇到的绝大部分问题。重点说三条不在表里但更值得注意的。
6.2 三条常规文档不写的经验
第一条:虚拟化环境下私网才是最大的不确定因素。物理机装 RAC 时私网基本不出问题,虚拟化平台就完全不一样——虚拟网卡的缓冲区、多队列、宿主机调度都会影响心跳包的时延。表现是节点稳定运行几天后突然重启,日志里找不到明显原因。我的做法是三件事:私网单独走一块虚拟网卡并开启多队列;把集群互联明确绑定到这块网卡上,别让集群自己猜;上线前用ping -f -s 8000对私网打一轮压测,观察丢包率是否为 0。这几步做完,节点的非预期重启基本就消失了。
第二条:所有“装完再调”的念头都要在开工前掐掉。RAC 的很多参数是“装的时候写进 OCR / 建库时写进控制文件”的,装完再改的代价远大于装前想清楚。典型例子是字符集、db_block_size、redo 大小、ASM 的 AU 大小。有人建完库发现db_block_size是 8K 想改成 16K,只能重建库;有人 ASM AU 用了 1M 想改成 4M,只能重建磁盘组。花半天做规划表,能省掉两天返工。
第三条:验收清单比安装过程更值得沉淀。装完之后我把那五条crsctl/asmcmd/ocrcheck命令写成脚本,每次部署、每次变更都跑一遍,输出存档。这套东西后来帮我在一次存储扩容后提前发现了 OCR 备份过期的问题,避免了更大的麻烦。交付一套 RAC,交的不只是“能跑”,还有“下次出问题时能查”。
最后分享一个我在实际操作中的体会:RAC 这东西的难点从来不在安装本身,安装只是把正确的决策执行一遍;真正耗时间的是每个决策背后的“为什么”。把规划做在前面、把校验点设在中途、把验收做成脚本,这套流程走顺之后,两节点 RAC 从裸机到建成库,我实测下来四个小时左右能完成,其中两个小时是在等 root.sh 和 DBCA 跑完。剩下那两个小时,基本都花在核对输出和记录上——这两小时不能省,省了后面一定要还。