Oracle 19c RAC安装:Standalone与Domain集群避坑

发布时间:2026/10/31 2:31:33
Oracle 19c RAC安装:Standalone与Domain集群避坑

简介:这份手册面向数据库管理员、系统运维与架构人员,聚焦在 Red Hat Enterprise Linux 7.6 上部署 Oracle 19c RAC 的落地过程,重点覆盖 GNS 配置 SCAN、Flex ASM 及 12.2 起 Standalone Cluster 与 Domain Service Cluster 两种集群模式的差异。内容按实施顺序展开,从 OS 环境检查、关闭 THP 并开启 Hugepages,到软件包安装、内核参数配置(Preinstall RPM 与手工方式)、CVU 校验、固定网络与 GNS 结合的网络规划,再到时钟同步等配置,便于按章节搭建环境并核对关键参数。包内共 1 个 docx 文件,约 160KB,以操作手册形式呈现,目录清晰,可作部署清单与配置参考。手册还结合常见问题给出解决思路与分析方法,帮助在 SCAN、GNS、ASM 或集群安装异常时快速定位。已有 719 人学习,适合系统掌握 19c RAC 部署与排错的中高级读者。

1. Oracle 19c RAC on Linux 7.6 安装手册:先分清 Standalone 与 Domain Services 两种集群

做 19c RAC Linux 7.6 安装,翻车点往往不在命令敲错,而在开局没分清 Standalone Cluster 和 Domain Services Cluster。这份手册把 OS 检查、THP/HugePages、内核参数、网络与 GNS、ASM UDEV、gridSetup.sh 到 dbca 整条链路拆成了能照着执行的步骤,适合手里有两三台机器、准备从零搭一套两节点 RAC 的 DBA 和系统工程师。它不教你 SQL 调优,只解决一件事:让集群装得上、起得来、节点之间能互相看见。

2. 系统底座:从 /proc 硬指标到 HugePages 的四个动作

2.1 环境检查:先把 /proc 里的硬指标读出来

装集群之前,主机层面有几项硬指标是绕不过去的,读不到或者读出来不达标,后面所有步骤都是白费。我一般不会一上来就跑安装器,而是先花五分钟把内存、swap、运行级别、内核版本、/tmp 和 /dev/shm 一次读全,把结果贴到变更单里留底,出问题时至少能证明"装之前是什么样"。

# 一次性把关键指标读全,输出留档 grep MemTotal /proc/meminfo grep SwapTotal /proc/meminfo runlevel uname -mr cat /etc/redhat-release df -h /tmp /dev/shm /u01

这几条命令看着简单,含义要拎清楚:MemTotal 是物理内存,两节点 RAC 每节点至少 8G,低于这个数安装器会直接拦;SwapTotal 在 4G 到 16G 区间建议等于内存,超过 16G 的部分固定取 16G,注意如果开了 HugePages,swap 的算法要减掉大页占用的那部分内存,否则算出来的值偏大;runlevel 要是 3 或 5,2 的话图形安装器起不来;uname -mr看内核版本,/etc/redhat-release看发行版小版本,两者要能对得上手册支持的矩阵。

检查项要求命令
内存每节点至少 8Ggrep MemTotal /proc/meminfo
Swap4G–16G 等于内存,超过 16G 取 16Ggrep SwapTotal /proc/meminfo
运行级别3 或 5runlevel
内核/发行版与支持矩阵一致uname -mr、cat /etc/redhat-release
/tmp至少 1Gdu -sh /tmp
/dev/shmtmpfs 挂载,权限 1777df -h /dev/shm
软件空间grid 至少 12G,Oracle 至少 10Gdf -h /u01

/u01 我一般直接给 100G,不是手册要求,是给自己留后悔药——19c 的 GIMR 虽然从 standalone 安装变成了可选项,但只要你哪天想补上,空间不够就得重装。这一步的产出是一张能贴进变更单的检查表,不是一堆散落的命令输出。

2.2 关闭 THP 与开启 HugePages 的顺序

透明大页面和 HugePages 的关系,是这条链路上最容易搞反的地方。THP 是内核自动合并 4K 页成 2M 页的机制,它的合并和碎片整理动作会带来不可预测的延迟抖动;HugePages 是预留的、固定大小的 2M 页池。两者同时开着,Oracle 的 SGA 有可能一部分落在 THP 上、一部分落在 HugePages 上,表现就是HugePages_Total明明有值,SGA 却没吃满,监控上看内存占用正常,实际性能忽高忽低。所以顺序永远是先关 THP、再开 HugePages。

# 确认 THP 当前状态,方括号落在哪一项就是当前值 cat /sys/kernel/mm/transparent_hugepage/enabled cat /sys/kernel/mm/transparent_hugepage/defrag # 备份后修改内核启动参数 cp /etc/default/grub /etc/default/grub.bak vi /etc/default/grub # 在 GRUB_CMDLINE_LINUX 引号内末尾追加:transparent_hugepage=never # 按固件类型重建 grub 配置 grub2-mkconfig -o /boot/grub2/grub.cfg # BIOS 机器 grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg # UEFI 机器 shutdown -r now cat /proc/cmdline # 确认参数已生效

这里有两个容易忽略的点。第一,grub2-mkconfig的输出路径必须和固件类型匹配,UEFI 机器上写成/boot/grub2/grub.cfg也不会报错,但重启后参数不生效,你会以为改成功了;第二,改完必须重启,/proc/cmdline是唯一可信的验证依据,/sys/kernel/mm/transparent_hugepage/enabled显示never也可能是运行时被临时改过,重启后又回去了。

HugePages 的大小要按 SGA 算,公式是 SGA 除以 2M 再向上取整,然后留 10% 左右余量。比如 SGA 规划 24G,24×1024÷2 = 12288 页,实际配 13312 页。如果这套集群后面还要加 GIMR(Domain Services Cluster 模式或者手工选了 GIMR),GIMR 自己的 SGA 默认约 1G,这部分要额外加进去,不能只按数据库 SGA 算。

# 写入大页数量 vi /etc/sysctl.conf vm.nr_hugepages = 13312 sysctl -p grep HugePages_Total /proc/meminfo grep HugePages_Free /proc/meminfo

配完大页还要动 memlock,单位是 KB,取值等于页数乘以 2048 再略放大一点,保证 oracle 和 grid 用户能把整块大页锁在内存里。写进/etc/security/limits.conf:

oracle soft memlock 27262976 oracle hard memlock 27262976 grid soft memlock 27262976 grid hard memlock 27262976

参数含义:27262976 KB 约等于 13312×2048,正好覆盖前面配的大页总量。memlock 给小了,数据库启动时会报 ORA-27102 out of memory,但报错信息不会直接告诉你是 memlock 问题,容易往 SGA 参数上查,绕一大圈。改完 limits 要重新登录会话才生效,ulimit -l能直接看出当前值。

2.3 软件包与 preinstall RPM 的取舍

软件包这块,RHEL 7 和 Oracle Linux 7 是两套思路。Oracle Linux 上直接装oracle-database-preinstall-19c,它会替你建 oracle 用户、建 oinstall 和 dba 组、写 sysctl、写 limits、顺手把 numa 关掉,省掉一堆手工活。但这个包默认按通用场景配参数,如果你的机器内存特别大或者 SGA 规划得比较激进,还是得回头看它写了什么,不能装完就当甩手掌柜。

# 配好 yum 源之后 yum repolist yum install -y oracle-database-preinstall-19c # 装完核对它改了什么 rpm -ql oracle-database-preinstall-19c tail -50 /var/log/oracle-database-preinstall-19c/backup/*

第二段命令是很多人会跳过的:preinstall 在修改 sysctl 和 limits 之前会把原文件备份到/var/log下面,出问题时这份备份就是还原点。RHEL 上没有这个包,只能手工装包,包清单按手册来:

yum install -y bc binutils compat-libcap1 compat-libstdc++ \ elfutils-libelf elfutils-libelf-devel fontconfig-devel \ glibc glibc-devel ksh libaio libaio-devel \ libX11 libXau libXi libXtst libXrender libXrender-devel \ libgcc librdmacm-devel libstdc++ libstdc++-devel libxcb \ make net-tools nfs-utils smartmontools sysstat

net-tools是 RAC 和 Clusterware 需要的,nfs-utils是 ACFS 需要的,后面如果要用 ACFS Remote,python、python-configshell、python-rtslib、python-six、targetcli 这几个也得补上。这些包单独看都不起眼,缺一个的表现是安装器跑到某个节点检查时给个模糊的 PRVF 报错,得回头翻日志才知道缺谁。

2.4 内核参数:手工写 sysctl 还是交给 preinstall

手工配内核参数时,我习惯单独放一个文件,不直接改/etc/sysctl.conf,这样升级或者回滚的时候好处理:

# /etc/sysctl.d/97-oracledatabase-sysctl.conf fs.aio-max-nr = 1048576 fs.file-max = 6815744 kernel.shmall = 2097152 kernel.shmmax = 4294967295 kernel.shmmni = 4096 kernel.sem = 250 32000 100 128 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

参数逐个说:kernel.shmall是共享内存总页数,按 4K 页算,2097152 页约等于 8G,机器内存大的话这个值要跟着放大;kernel.shmmax是单个共享内存段的上限,4294967295 是 4G 减 1,SGA 超过 4G 且没开大页时会撞上这个限制;kernel.sem四个值分别是信号量集合数、每个集合的信号量数、可同时执行的操作数、系统级信号量总数,改小了高并发下会报 ORA-27154;ip_local_port_range起点抬到 9000,是为了避开监听器常用的低位端口。

# 生效并核对 /sbin/sysctl --system /sbin/sysctl -a | grep -E 'shmall|shmmax|sem|aio-max-nr'

如果走的是 preinstall 路线,这一步它已经替你做了,但还是要跑一遍核对,因为不同版本的 preinstall 包写入的参数值会有差异。CVU 是可选项,只有在不用 preinstall 的时候才需要单独装 cvuqdisk;装之前先rpm -qi cvuqdisk看有没有旧版本,有的话先卸再装,环境变量CVUQDISK_GRP指向 oinstall,否则后面跑runcluvfy.sh会报权限问题。

3. 网络与 GNS:把 SCAN 塞进被委托的子域

3.1 固定配置与 GNS 混合:什么时候值得上 GNS

网络这块,19c 给了两条路:全固定,或者固定加 GNS。全固定的意思是 Public、Private、VIP、SCAN 全部手工写死,DNS 只负责解析 SCAN 的三条 A 记录;GNS 模式则是把 VIP、Private IP、SCAN VIP 的分配权交给 Grid Naming Service,安装时只需要给 GNS 一个固定 IP 和一个子域。

我的判断标准很直接:节点数固定、IP 规划已经进了 CMDB 的环境,全固定最省事,出了问题排查路径最短;节点数可能扩、或者希望后续加节点时少改 DNS 的,才值得上 GNS。GNS 的代价是你必须把 DNS 的架构一起理清楚,尤其是子域委托这一层,配错了安装器会卡在 SCAN 配置页面反复重试。

还有几条硬约束要提前记住:整条链路要么全 IPv4,要么全 IPv6,不能混;VIP 从 18c 起是可选的,但只能"全有或全无",不能只给部分节点配 VIP;Private 最多四个网卡参与 HAIP,超过四个的部分自动降为冗余,所以别指望靠堆网卡提升私网带宽;Public、VIP、SCAN VIP 必须在同一子网段;名字里只能用字母数字和连字符,下划线在 Public/VIP 名称上是不允许的。

3.2 /etc/hosts 与正解文件的写法

先落 hosts,把公网、私网、VIP、GNS 四类地址写清楚,SCAN 不写进 hosts,交给 DNS:

cat >> /etc/hosts <<'EOF' 192.168.204.11 pub19-node1.rac.example pub19-node1 192.168.204.12 pub19-node2.rac.example pub19-node2 10.10.10.41 priv19-node1.rac.example priv19-node1 10.10.10.42 priv19-node2.rac.example priv19-node2 192.168.204.21 vip19-node1.rac.example 192.168.204.22 vip19-node2.rac.example 192.168.204.10 gns19.rac.example gns19 EOF

这里每行都带了短名,是因为 Clusterware 内部有些组件会用短名做解析,只写 FQDN 在某些版本上会出现节点间互相认不出的情况。私网走 10.10.10.0/24 这一段,和公网 192.168.204.0/24 完全分开,不要图省事把私网也塞进公网段,HAIP 的流量和公网流量混在一起,出问题时抓包都抓不清楚。

DNS 用 bind,主配置里三个 zone:正向域、公网反解、私网反解。

// /etc/named.conf 节选 options { directory "/var/named"; allow-query { 192.168.204.0/24; }; recursion yes; allow-transfer { none; }; }; zone "rac.example" IN { type master; file "named.rac.example"; }; zone "204.168.192.in-addr.arpa" IN { type master; file "named.192.168.204"; }; zone "10.10.10.in-addr.arpa" IN { type master; file "named.10.10.10"; };

allow-query收窄到集群所在网段,比any安全;allow-transfer设 none,避免被人拉走整份 zone 文件。反解域的名字是 IP 段倒序加.in-addr.arpa,192.168.204 倒过来就是 204.168.192,写错了named-checkconf不报错,但反解查不出来。

正解文件是整段配置里最关键的一个:

$TTL 600 @ IN SOA rac.example. admin.rac.example. ( 2024010101 ; serial 1D ; refresh 1H ; retry 1W ; expire 3H ) ; minimum @ IN NS master.rac.example. master IN A 192.168.204.12 scan19.vip.rac.example. IN A 192.168.204.33 scan19.vip.rac.example. IN A 192.168.204.34 scan19.vip.rac.example. IN A 192.168.204.35 vip19-node1.rac.example. IN A 192.168.204.21 vip19-node2.rac.example. IN A 192.168.204.22 pub19-node1.rac.example. IN A 192.168.204.11 pub19-node2.rac.example. IN A 192.168.204.12 priv19-node1.rac.example. IN A 10.10.10.41 priv19-node2.rac.example. IN A 10.10.10.42 vip.rac.example. IN NS gns.rac.example. gns.rac.example. IN A 192.168.204.10

最后两行是整个 GNS 配置的枢纽:第一行声明vip.rac.example这个子域的权威服务器是gns.rac.example,第二行给出 GNS 的地址。SCAN 的三条 A 记录必须写在scan19.vip.rac.example这个名下,也就是必须落在被委托出去的那个子域里。原因是安装器在配置 GNS 时,会把 SCAN 的解析权一并交给 GNS 管理,如果 SCAN 名不在委托子域内,GNS 收不到这个域的查询,SCAN VIP 就注册不上。

3.3 GNS 子域委托:SCAN 必须落在被委托的子域下

这条约束值得单独拎出来讲,因为它是这条链路上最反直觉的一处。很多人习惯把 SCAN 写成scan19.rac.example,觉得域名短一点好看,但在 GNS 模式下这个写法会让安装器在 SCAN 配置页面一直转圈,日志里能看到 GNS 反复尝试注册 SCAN 却拿不到应答。原因不复杂:rac.example这个域的权威服务器是 master,GNS 只被委托了vip.rac.example,它对rac.example下的名字没有发言权。

所以在 gridSetup.sh 里填 GNS 信息时,两个字段要对应上:GNS VIP 填192.168.204.10,subdomain 填vip.rac.example,SCAN 名填scan19.vip.rac.example。三个值是一组,改一个就要同步改另外两个。如果同时上了 DHCP,VIP、Private、SCAN 都可以由 GNS 动态分配,但 DNS 这边的委托关系不变,还是得先把子域指过去。

3.4 反解与验证:别等到安装器报错才查

反解文件的作用在 RAC 里比一般场景更明显,Clusterware 启动时会做大量正向和反向解析,反解缺失的表现是节点启动慢、CSSD 心跳超时、日志里一堆名字解析失败但不说具体缺哪条。

$TTL 600 @ IN SOA rac.example. admin.rac.example. ( 2024010101 ; serial 3H ; refresh 15M ; retry 1W ; expire 1D ) ; minimum @ IN NS master.rac.example. 11 IN PTR pub19-node1.rac.example. 12 IN PTR pub19-node2.rac.example. 21 IN PTR vip19-node1.rac.example. 22 IN PTR vip19-node2.rac.example. 33 IN PTR scan19.vip.rac.example. 34 IN PTR scan19.vip.rac.example. 35 IN PTR scan19.vip.rac.example.

写完之后不要急着重启 named,先做静态检查再做动态查询:

named-checkconf /etc/named.conf named-checkzone rac.example /var/named/named.rac.example named-checkzone 204.168.192.in-addr.arpa /var/named/named.192.168.204 systemctl enable --now named # 正解、反解、SCAN 三条都要查 dig +short pub19-node1.rac.example dig -x 192.168.204.11 +short dig +short scan19.vip.rac.example

named-checkzone会检查 SOA 序列号、NS 记录、CNAME 冲突这些静态问题,但它不检查委托关系是否生效。SCAN 那条查询要返回三个不同 IP 才算对,如果只返回一个,回去看三条 A 记录是不是写在同一行被合并了,或者 TTL 缓存还没过期。全部通过之后,再在另一个节点上用同样的命令复查一遍,确保两台机器看到的解析结果完全一致——这一点在后面的避坑章节里还会提到,解析不一致是集群起不来的头号原因。

4. 存储与杂项:ASM UDEV 绑定和 limits 的边界

4.1 ASM 磁盘的 UDEV 绑定

ASM 磁盘的权限问题是个老话题,但每年还是有人在 660 权限配好了、属组也对了的情况下起不来集群。核心原因是 UDEV 规则的匹配依据写错了。RHEL 7 上用scsi_id拿磁盘唯一标识,不要用已经被废弃的参数:

# 先看盘,确认设备名和序列号 lsblk -o NAME,SIZE,TYPE,SERIAL /usr/lib/udev/scsi_id -g -u -d /dev/sdb /usr/lib/udev/scsi_id -g -u -d /dev/sdc

拿到标识串之后写规则文件,注意文件名前缀决定执行顺序,用 99 开头保证在其他规则之后生效:

# /etc/udev/rules.d/99-oracle-asmdevices.rules KERNEL=="sd*", ENV{DEVTYPE}=="disk", SUBSYSTEM=="block", \ PROGRAM=="/usr/lib/udev/scsi_id -g -u -d /dev/$name", \ RESULT=="36000c29a1b2c3d4e5f60718293a4b5c", \ SYMLINK+="asm-disk1", OWNER="grid", GROUP="asmadmin", MODE="0660"

这段规则的执行逻辑是:先按 KERNEL 和 SUBSYSTEM 筛出块设备,再调用scsi_id拿标识,和 RESULT 里的字符串比对,命中就创建/dev/asm-disk1软链接并把属主属组和权限设好。常见的错误是把 RESULT 写成序列号而不是 WWID,两者长得像但值不一样;另一个错误是用了多路径却没取/dev/mapper下设备的 wwid,规则匹配到的是底层物理盘,多路径切换后软链接就断了。

udevadm control --reload-rules udevadm trigger --type=devices --action=change ls -l /dev/asm-disk*

trigger那行的--action=change不能省,省了之后规则重载了但不会对已存在的设备重新求值,你会以为规则没生效。检查时看软链接指向的设备对不对,权限是不是brw-rw----加 grid:asmadmin,两个条件都满足才算过。

4.2 NAS、Direct NFS 与 I/O Scheduler

如果 OCR 和 voting disk 不放 ASM 而是放共享文件系统,19c 是支持的——从 19.3 起,Standalone Cluster 可以把 OCR 和 voting disk 直接放在共享文件系统上。走 NAS 的话,挂载参数里actimeo=0、noac这类选项要按存储厂商的建议来,别自己拍脑袋加,缓存属性不对会让 voting disk 的心跳写入出现延迟。

Direct NFS 是另一条路,它绕过操作系统的 NFS 客户端直接和 NAS 通信,配置上要在$GRID_HOME/lib和$ORACLE_HOME/lib下放对应版本的libnfsodm19.so,然后建一个odm目录把挂载信息写进去。这条路对网络和 NAS 端的要求比较高,小文件多的场景收益不明显,大块顺序读的场景才值得折腾。

I/O Scheduler 这块,机械盘用deadline,SSD 或 NVMe 用none,别用cfq。临时改一条命令就够,持久化要靠 UDEV:

cat /sys/block/sdb/queue/scheduler echo deadline > /sys/block/sdb/queue/scheduler
# /etc/udev/rules.d/60-iosched.rules ACTION=="add|change", KERNEL=="sd*", ATTR{queue/scheduler}="deadline" ACTION=="add|change", KERNEL=="nvme*", ATTR{queue/scheduler}="none"

ASM 自己有一层 I/O 调度,操作系统这层再叠一个复杂的调度器意义不大,反而增加不可控的延迟。这条规则不是装完就必须配,但如果你的存储是高 IOPS 的闪存,配了之后 AWR 里的单块读延迟会更稳定。

4.3 limits.conf、SSH 超时与图形界面

limits 这块,除了前面提的 memlock,还有 nproc、nofile、stack 三项要一起配。只配 oracle 不配 grid 是最常见的遗漏,grid 用户跑 Clusterware,进程数和文件句柄开得比数据库还多。

# /etc/security/limits.d/99-grid-oracle-limits.conf grid soft nproc 16384 grid hard nproc 16384 grid soft nofile 65536 grid hard nofile 65536 grid soft stack 10240 grid hard stack 32768 oracle soft nproc 16384 oracle hard nproc 16384 oracle soft nofile 65536 oracle hard nofile 65536 oracle soft stack 10240 oracle hard stack 32768

写进/etc/security/limits.d/比直接改/etc/security/limits.conf好维护,文件名用 99 开头保证最后加载。改完必须重新登录会话,su - grid -c 'ulimit -n'能直接验证。SSH 超时是个小配置但影响很大,安装过程中要反复在节点间跑 ssh,会话断了安装器就挂在那里:

echo "ClientAliveInterval 300" >> /etc/ssh/sshd_config echo "ClientAliveCountMax 0" >> /etc/ssh/sshd_config systemctl reload sshd

ClientAliveInterval 300表示服务端每 300 秒发一次探测,ClientAliveCountMax 0表示不重试直接断。这两个值组合起来会让空闲会话在 300 秒后断开——如果你不希望它断,把 CountMax 设成 3 而不是 0,给三次机会。图形界面配置是给 gridSetup.sh 和 dbca 用的,如果节点上没有完整桌面环境,至少要装 X11 相关的包并配好 DISPLAY,或者用静默模式加响应文件,后者在批量部署时更稳。

4.4 时钟同步与关闭 X11 Forward

时钟同步在 RAC 里不是可选项,节点间时间差超过阈值,CSSD 心跳判断就会出问题,日志里表现为节点被踢出集群但不说原因。chrony 是 RHEL 7 上的默认选择:

yum install -y chrony vi /etc/chrony.conf # 加一行指向内网时间源:server 10.10.10.1 iburst systemctl enable --now chronyd chronyc sources -v

iburst让 chrony 在启动时快速发一批包同步,比默认的慢慢调快得多。chronyc sources -v输出里每个源前面有个标记,^*表示当前选中的同步源,^?表示不可达,看不懂标记就看chronyc tracking里的 System time 偏移量,控制在毫秒级算正常。

X11 Forward 要关掉,/etc/ssh/sshd_config里X11Forwarding no,原因是 RAC 节点之间会建立大量 ssh 连接,开着转发会让每个连接多占资源,而且日志里会混入转发相关的噪声。图形安装的时候用 VNC 或者直接在本地控制台操作,别指望 X11 转发跑 dbca,那个界面响应速度能让你怀疑人生。

5. 避坑排查:五条从现场捡回来的记录

5.1 集群节点起不来:先看 ohasd 再看 CSSD

现象是crsctl stat res -t在某一个节点上完全没输出,或者输出里所有资源都是 OFFLINE,/u01/app/grid/diag/crs/<节点>/crs/trace/alert.log里有CSSD相关报错。原因通常不在 Clusterware 本身,而在网络解析或私网网卡。第一步查/etc/hosts和 DNS 的解析结果是否在两个节点上完全一致,尤其注意有没有残留的旧 IP;第二步确认私网网卡是 up 状态且 MTU 一致;第三步看防火墙,firewalld和iptables都要确认放行了集群端口。

# 三台机器上都跑一遍,结果必须一致 getent hosts pub19-node1.rac.example getent hosts priv19-node1.rac.example ip addr show | grep -E 'inet |UP' systemctl status firewalld

如果解析和网卡都对,再去看ohasd的日志,/var/log/messages里搜ohasd,常见的是权限问题导致ohasd.bin启动失败,比如 grid 用户对$GRID_HOME的属主被改过。这类问题的解决方式是修权限而不是重装,chown -R grid:oinstall $GRID_HOME之后crsctl start crs。

5.2 gridSetup.sh 卡在 SSH 互信那一步

现象是安装器跑到"节点连通性检查"页面就一直转,或者提示某个节点 ssh 不通,但手工在终端里ssh是通的。原因是之前做过 ssh 免密配置,~/.ssh/known_hosts里存了旧的 host key,安装器用 grid 和 oracle 两个用户分别去连,其中一个用户的 known_hosts 没清。解决方式是先把所有节点的known_hosts备份后清空,再让安装器自己重建互信:

# 两个用户都要做,先备份再清 for u in grid oracle; do su - $u -c 'cp ~/.ssh/known_hosts ~/.ssh/known_hosts.bak 2>/dev/null; rm -f ~/.ssh/known_hosts' done # 手工验证一遍双向连通 su - grid -c "ssh -o StrictHostKeyChecking=no pub19-node2.rac.example date"

另一个隐蔽原因是 SELinux 处于 enforcing 且没有对应的策略,ssh 本身通但安装器调用的某些操作被拦。装之前把 SELinux 设成 permissive 是常规做法,装完再按需收紧,别在 enforcing 状态下硬装。

5.3 ASM 磁盘权限 660 却认不到

现象是/dev/asm-disk*软链接在,权限也是brw-rw----加 grid:asmadmin,但asmcmd lsdsk看不到,或者安装器扫描磁盘时列表是空的。原因有三个常见分支:一是 UDEV 规则的 RESULT 匹配串写错,scsi_id拿到的值和规则里写的不一致;二是有多路径,规则匹配的是/dev/sdb但实际应该匹配/dev/mapper/mpathX;三是规则文件没有重新 trigger,软链接是上一次的残留。

# 逐个核对 /usr/lib/udev/scsi_id -g -u -d /dev/sdb udevadm info --query=all --name=/dev/sdb | grep -iE 'wwid|serial' ls -l /dev/asm-disk* udevadm control --reload-rules && udevadm trigger --action=change

排查顺序建议从"设备是否被多路径接管"开始,multipath -ll看一眼,如果盘在多路径下面,UDEV 规则要基于 wwid 写,不能用/dev/sd*做 KERNEL 匹配。改完规则一定要重新 trigger 并重新ls -l确认。

5.4 HugePages 配了但 SGA 没吃上

现象是grep HugePages_Total /proc/meminfo有值,但HugePages_Free几乎等于 Total,数据库启动后 SGA 还是走普通页,/proc/meminfo里的AnonHugePages不为零。原因通常是三个:memlock 配小了,SGA 锁不进大页;THP 没真正关掉,运行时被重新打开;SGA 总量超过了大页池容量,数据库退回到普通页。

# 三项一起看 grep -E 'HugePages|AnonHugePages' /proc/meminfo ulimit -l cat /sys/kernel/mm/transparent_hugepage/enabled

解决方法是按实际 SGA 重算页数,memlock 调到页数×2048 再放大 5%,然后重启数据库实例。注意改完大页数量不需要重启操作系统,但需要确认没有其他进程占着大页不释放,grep -i huge /proc/*/smaps能看出谁在用。

5.5 SCAN VIP 只在单节点上漂

现象是srvctl status scan显示三个 SCAN VIP 都只在同一个节点上,客户端连 SCAN 时好时坏。原因基本锁定在 DNS:SCAN 名只解析出一个 IP,或者三个 IP 里有两个指向同一个地址,客户端轮询自然就落在一个节点上。另一个可能是 GNS 的子域委托没生效,SCAN 注册失败,Clusterware 退回到本地解析。

# 从集群外的机器上查,模拟客户端视角 dig +short scan19.vip.rac.example nslookup scan19.vip.rac.example 192.168.204.12 srvctl config scan srvctl status scan

dig要返回三个不同 IP,srvctl config scan里的三个 SCAN VIP 要和 DNS 里的三条 A 记录一一对应。对不上就回去改正解文件,改完rndc reload并清客户端 DNS 缓存,再srvctl relocate scan让 SCAN VIP 重新分布。

6. 装完别急着交付:一轮滚动重启验证和三条体检命令

安装器跑完、dbca 建完库,不代表这套 RAC 能扛。我见过太多"装完当天好好的、第二天节点起不来"的案例,根因都是装完没做重启验证。交付前至少要做一轮滚动重启:先停一个节点,确认另一个节点上的实例和监听器正常接管,再启动、再换另一个节点重复,两轮下来才算验证了 VIP 漂移和实例故障转移。

体检命令就三条,按顺序跑:

检查项命令期望结果
集群资源crsctl stat res -t所有资源在各自节点 ONLINE,无 UNKNOWN
节点成员olsnodes -n列出全部节点,编号连续
ASM 磁盘组asmcmd lsdg各磁盘组 MOUNTED,可用空间与规划一致

crsctl stat res -t输出里重点看 GIMR 相关的资源(如果配了)、ora.LISTENER_SCAN1.lsnr、ora.scan1.vip、ora.<节点>.vip这几类,任何一项是 INTERMEDIATE 或者状态在两个节点间反复跳,都说明还有没排干净的问题。asmcmd lsdg的Usable_file_MB要留出至少 20% 余量,低于这个数后面加数据文件会报空间不足。

进阶一点的验证是跑一次cluvfy comp healthcheck -all,它会把集群的各个组件巡一遍,输出比crsctl细,缺点是慢,节点多的环境跑一次十几分钟。我一般放在变更窗口的最后做,跑完把输出存档,下次出问题时至少有基线可比。

还有一个习惯:装完之后立刻在/etc/下面做个快照,tar czf /root/etc-backup-$(date +%F).tar.gz /etc/hosts /etc/named.conf /var/named /etc/sysctl.d /etc/security/limits.d /etc/udev/rules.d,把这次改过的所有配置打成一个包。后面不管是谁接手、不管过了多久,出问题时解压出来就能比对出哪一处被改过。从那以后我每次装 RAC,交付清单里都强制带这一条——不是因为它技术含量高,是因为它救过我两次,一次是 hosts 被人加了条错误记录,一次是 UDEV 规则被别的运维覆盖了。希望帮到你。

本文还有配套的精品资源,点击获取