ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

19c RAC 安装前关键配置:HugePages、GIMR 与 SCAN

19c RAC 安装前关键配置:HugePages、GIMR 与 SCAN

简介:这是一份面向Oracle数据库管理员与RAC实施人员的安装手册,聚焦Red Hat Enterprise Linux 7.6环境下Oracle 19c RAC的部署与配置,适合具备一定Linux和数据库基础、需要完成实验搭建或生产前期验证的读者参考。手册兼顾原理说明与实操落地,适合用于实验环境搭建、实施前检查及问题复盘。资源包仅含1个docx文档,大小约160KB,内容按安装流程组织,便于按章节查阅。文档以GNS配置SCAN为主线,介绍Flex ASM的配置思路及不同版本间的变化,并说明自12.2起集群分为Standalone Cluster与Domain Service Cluster两种模式。目录覆盖OS环境检查、关闭THP与开启Hugepages、安装软件包、内核参数配置、固定网络与GNS+固定网络配置、时钟同步等环节,还整理了配置问题解决与分析问题的方法。已有719人学习,可作为梳理19c RAC安装步骤、理解GNS与集群模式差异的案头资料。

1. 先分清 Standalone 与 Domain Services,再决定装哪一套 19c RAC

搜索 19c RAC Linux 7.6 安装,十条结果里有九条从 gridSetup.sh 的图形界面开始截图,而真正让人返工的活儿全在打开图形界面之前:THP 忘了关、hugepages 少算了 GIMR 那 1G、SCAN 名没落在 GNS 托管的子域里导致三个地址只出来一个。这份 docx 手册把顺序固定下来了,依次是 OS 检查、关透明大页、开大页、装包、改内核、配网、杂项,最后才是 gridSetup.sh 和 dbca,中间还穿插了 Flex ASM 与 Standalone/Domain Services 两种集群模式的差异说明。

它面向的是两到三节点、用共享存储或 NAS 的 Standalone Cluster,网络部分提供了「全手工固定」和「GNS 管 VIP/SCAN」两条路。手里有机器、要在一周内把库跑起来的人,照着抄能省掉大半天;装过一次但总在 cluvfy 那一步卡住的人,重点看第 3 章和第 5 章。

2. OS 前置与 HugePages:先把 memlock 和 nr_hugepages 算准再重启

2.1 六项硬指标:用几条命令把不合格的机器挡在安装之前

装 RAC 最怕的不是报错,是装到 70% 才发现 /tmp 不够或者 swap 给少了,然后回退重来。手册开篇列的检查项不多,但每一项都是硬性要求,我习惯在拿到机器后先统一跑一遍,结果直接贴到工单里存档:

# 内存与 swap grep MemTotal /proc/meminfo grep SwapTotal /proc/meminfo # 临时空间与共享内存 df -h /tmp /dev/shm # 软件安装空间(grid 与 oracle 建议分开挂) df -h /u01 /u02 # 运行级别、内核、发行版 runlevel uname -mr cat /etc/redhat-release

先说内存,单节点 8G 是门槛线,但这只是「能装起来」,真跑两套实例建议 32G 起。swap 的规则是分段的:物理内存在 4G 到 16G 之间时,swap 给到和内存一样大;超过 16G 的部分,swap 固定给 16G 就够。这里有个容易被跳过的前提,手册专门点了出来,如果开了 HugePages,计算 swap 时要先减掉分给大页的那部分内存。举个具体的例子,一台 16G 内存的机器划了 8G 给大页,等效可用内存只剩 8G,那 swap 按规则应该给 8G 而不是 16G,给多了是浪费,给少了在内存压力下会直接触发 OOM。

/tmp至少 1G,这是安装程序解压和写临时文件的目录,跑 gridSetup 时里面会有几个 G 的临时产物,1G 只是下限。/dev/shm要确认是 tmpfs 且权限为 1777,权限不对时 dbca 建库阶段会以很奇怪的方式失败。软件空间方面,Grid 基础架构至少 12G,数据库软件至少 10G,手册建议直接给 100G 预留,因为后面还有补丁、日志、诊断收集(TFA)往里写东西。运行级别必须是 3 或 5,2 或者 4 这种非标准级别下集群的启动脚本可能不会被拉起。

提示:这几条命令的结果我一般会存成一个文本文件,跟着安装记录一起归档。半年后回看「当时那台机器为什么装得慢」,答案基本都在里面。

2.2 关 THP:改 GRUB 与两条重建路径

透明大页(THP)是内核的动态合并机制,对数据库来说它的行为不可控,什么时候合并、合并哪一块都不是运维能决定的,Oracle 明确要求关掉。先确认当前状态:

cat /sys/kernel/mm/transparent_hugepage/enabled cat /sys/kernel/mm/transparent_hugepage/defrag

输出里方括号落在哪一项就是当前值。如果显示[always] madvise never,说明 THP 开着,整理碎片的功能(defrag)大概率也开着。临时改(不重启生效,仅用于验证)可以往这两个文件里 echo never,但持久化必须走内核参数:

cp /etc/default/grub /etc/default/grub.bak.$(date +%F) # 幂等追加:先判断是否已经加过,避免重复执行写出两遍 grep -q 'transparent_hugepage=never' /etc/default/grub || \ sed -i 's/^\(GRUB_CMDLINE_LINUX=".*\)"$/\1 transparent_hugepage=never"/' /etc/default/grub # BIOS 启动的机器 grub2-mkconfig -o /boot/grub2/grub.cfg # UEFI 启动的机器二选一,别两条都跑 grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg

GRUB_CMDLINE_LINUX这一行末尾是有引号的,sed 的替换必须把右引号一起匹配进去,否则新参数会被写到引号外面,grub2-mkconfig 生成配置时直接忽略。另外这条命令重复执行会追加多遍transparent_hugepage=never,所以前面加了grep -q做幂等判断。重建时注意区分 BIOS 与 UEFI:/boot/grub2/grub.cfg和/boot/efi/EFI/redhat/grub.cfg是两个文件,写错位置重启后参数不生效,看起来像是「改了没用」。改完必须重启,重启后用cat /proc/cmdline确认参数在里面,再回去看/sys/kernel/mm/transparent_hugepage/enabled是否变成always madvise [never],两个都对才算完。

2.3 HugePages 与 memlock:一个公式解决大部分 ORA-27102

THP 关掉之后,SGA 要么用 4K 小页,要么用传统大页。生产环境一律用大页,原因很直接:页表项少、TLB 命中高、内存不会被换出。代价是必须提前算准,算少了实例起不来并抛 ORA-27102,算多了内存白占着别人用不了。

计算逻辑只有一条:把单节点上所有要用大页的实例 SGA 加起来,除以页大小并向上取整。19c Standalone 可以选择不配 GIMR,一旦配了,GIMR 自己的 SGA 大约占 1G,这部分同样走大页,必须算进去。手册反复强调的就是这 1G,很多人第一次装漏掉它,结果集群起来了、ASM 起来了,dbca 建库时挂了。

#!/bin/bash # 单节点上所有 Oracle 实例的 SGA 之和(单位 GB) SGA_GB=8 # 配了 GIMR 填 1,Standalone 不配 GIMR 填 0 GIMR_GB=1 # 余量系数,留 10% 防后续加实例 SLACK=1.1 PAGE_KB=$(grep Hugepagesize /proc/meminfo | awk '{print $2}') # 通常 2048 TOTAL_MB=$(( (SGA_GB + GIMR_GB) * 1024 )) HP=$(awk -v m="$TOTAL_MB" -v p="$PAGE_KB" -v s="$SLACK" 'BEGIN{printf "%d", (m*s)/p + 1}') echo "vm.nr_hugepages = $HP" echo "oracle soft memlock $(( HP * PAGE_KB ))" echo "oracle hard memlock $(( HP * PAGE_KB ))"

几个参数的含义要说清楚。PAGE_KB从/proc/meminfo的 Hugepagesize 读,x86_64 上一般是 2048,不要硬编码成 2M,虚拟机或某些内核配置下可能不同。memlock的单位是 KB,这是ulimit -l的单位,必须不小于大页占用的总量,否则实例连锁定内存的权限都拿不到,报错信息还很含糊。SLACK我一般取 1.1,纯按 SGA 算得太紧,后面加个实例或者调大 SGA 就得重算。

按 SGA 8G、配 GIMR 算下来是 4608 个大页,memlock 约 9437184 KB。写进/etc/security/limits.conf或/etc/security/limits.d/下单独一个文件都行,但要注意后加载的会覆盖先加载的,preinstall RPM 会生成自己的 limits 文件,手工改 limits.conf 可能被它盖掉,这点在第 5 章细说。

场景SGAGIMRnr_hugepagesmemlock(KB)
不配 GIMR,单实例8G045069228288
配 GIMR,单实例8G1G506910381312
配 GIMR,双实例12G1G732214995456

改完vm.nr_hugepages后,用sysctl -p或写进/etc/sysctl.conf的方式让其持久化。已经运行一段时间、内存碎片的机器上,直接 echo 新值到/proc/sys/vm/nr_hugepages可能分配不到目标数量,这种情况只能重启,没有别的办法。

2.4 limits.conf、I/O 调度与 SSH 超时:几个容易被跳过的杂项

操作系统杂项里,三项最值得单独确认。第一项是进程数限制,RAC 节点上 ASM 加实例加监听加集群ware 的进程数量不小,nproc 给到 16384 比较稳妥:

cat > /etc/security/limits.d/99-oracle-rac.conf <<'EOF' grid soft nproc 16384 grid hard nproc 16384 grid soft nofile 65536 grid hard nofile 65536 oracle soft nproc 16384 oracle hard nproc 16384 oracle soft nofile 65536 oracle hard nofile 65536 EOF su - grid -c 'ulimit -n; ulimit -u'

文件名用 99 开头,保证字典序上排在 preinstall 生成的 19c 文件之后,后加载覆盖先加载这一条在 limits.d 里同样成立。改完一定要用su - grid切过去验证,直接在当前会话ulimit看到的是旧值,因为 limits 是在登录时生效的。这两条如果漏掉,典型症状是 dbca 建库到一半报「ORA-00020 maximum number of processes exceeded」或者监听起不来。

第二项是 I/O 调度器。共享存储上跑 ASM,调度器建议用 deadline,RHEL 7 默认一般是 deadline 或 noop,但虚拟化平台给的盘有时会是 mq-deadline 或 bfq,需要确认:

for d in /sys/block/sd*/queue/scheduler; do echo "$d: $(cat $d)"; done echo deadline > /sys/block/sdb/queue/scheduler

用 echo 改只对当前生效,重启就回默认。持久化的做法是在第 4 章的 UDEV 规则里顺带写一条ATTR{queue/scheduler}="deadline",这样盘插上就是对的。多路径环境下要改/sys/block/dm-*/queue/scheduler而不是底层 sd 设备。

第三项是 SSH 超时。安装过程动辄两三个小时,如果 SSH 会话中途断开,图形安装界面或 root.sh 会跟着挂死,回滚都回不干净。服务端改/etc/ssh/sshd_config的ClientAliveInterval 300和ClientAliveCountMax 12,客户端在自己的~/.ssh/config里加ServerAliveInterval 60,两边都设更保险。

3. 软件包与内核参数:preinstall RPM 与手写 sysctl 的两条路

3.1 软件包清单:哪些是必需的,哪些是为 ACFS 预留的

手册列的包不少,按用途分组看会清楚很多。基础库里 binutils、glibc、glibc-devel、libgcc、libstdc++、libstdc++-devel、make、ksh、compat-libcap1、compat-libstdc++ 这十几个是硬依赖,缺任何一个 runInstaller 的预检查都过不去。其中 ksh 现在很少用了,但 root.sh 里确实调用了它,别图省事跳过。磁盘和异步 I/O 相关的 libaio、libaio-devel 一定要装,ASM 靠它做异步读写,缺了以后表现是性能莫名很差而不是直接报错。

X11 那一组 libX11、libXau、libXi、libXtst、libXrender、libXrender-devel、fontconfig-devel 是为图形化安装界面准备的。现在很多环境根本不装图形界面,用静默安装可以省掉这一组,但如果打算用 VNC 或 X11 转发跑 gridSetup,这些必须齐。网络相关的 net-tools、nfs-utils、librdmacm-devel(InfiniBand 才用得上)按实际环境选。最后一组 python、python-configshell、python-rtslib、python-six、targetcli 是 Oracle ACFS Remote 的依赖,不用 ACFS 可以不加。

一次装完的命令大概是这样:

yum install -y binutils bc 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 libstdc++ libstdc++-devel libxcb make net-tools nfs-utils \ python python-configshell python-rtslib python-six targetcli \ smartmontools sysstat unzip

装完用rpm -q批量核对一遍,比在预检查报错后再回头查要快得多。unzip不在手册列表里,但解压 Grid 安装包用得上,顺手加上。

3.2 preinstall RPM 做了什么,以及为什么我还要复核

Oracle Linux 和 RHEL 都能用oracle-database-preinstall-19c这个包把大部分 OS 配置一次做完,省掉手工改五六个文件的麻烦:

yum install -y oracle-database-preinstall-19c rpm -ql oracle-database-preinstall-19c

它主要做四件事:创建 oracle 用户和 oinstall、dba、asmadmin、asmdba、asmoper 等组;把内核参数写进/etc/sysctl.d/97-oracledatabase-sysctl.conf;把资源限制写进/etc/security/limits.d/oracle-database-preinstall-19c.conf;部分版本还会顺带设置numa=off。装完不代表就对了,我一般会复核三处:

sysctl -a | grep -E 'shmmax|shmall|shmmni|file-max|aio-max-nr|ip_local_port_range' grep -r 'memlock\|nofile\|nproc' /etc/security/limits.d/ id oracle; id grid

这里有个坑:preinstall 生成的 sysctl 文件名是 97 开头,很多人手工又建一个 97-oracledatabase-sysctl.conf 覆盖它,或者建了 99 但里面只写了两三个参数,结果把 97 里的其它参数「部分覆盖」得乱七八糟。更稳的做法是:装了 preinstall 就不再手工写 sysctl,要调哪个参数单独用sysctl -w验证效果,确认后再追加到一个 99 开头的新文件里,且只写要覆盖的那几行。

还有一个前置条件,preinstall 不会自动建 grid 用户,它建的是 oracle 用户。可以手工建,也可以直接把用户建好再装包:

groupadd -g 54321 oinstall groupadd -g 54322 dba groupadd -g 54323 asmadmin groupadd -g 54324 asmdba groupadd -g 54325 asmoper useradd -u 54321 -g oinstall -G dba,asmdba,asmadmin,asmoper grid useradd -u 54322 -g oinstall -G dba,asmdba,asmadmin oracle

UID/GID 在两个节点上必须完全一致,否则后面 SSH 互信和共享目录权限会出问题。这一点手册写在用户组目录配置那一节,但很容易在「两个节点分别装包」的时候被忽略。

3.3 手写 sysctl:shmmax 与 shmall 的换算关系

不用 preinstall 的话,内核参数得自己写。手册给的那份值是经过验证的,可以直接抄:

# /etc/sysctl.d/99-oracle-rac.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.sem是四个值一组,依次是每个信号量集的信号量个数、系统级信号量总数、每次 semop 调用的最大操作数、系统级信号量集个数,ASM 和实例启动时并发申请信号量,这组值小了会在高并发下报「ORA-27154」。kernel.shmall是共享内存总页数,kernel.shmmax是单个共享内存段的最大字节数,两者单位不同,这是最容易算错的地方:

PAGE=$(getconf PAGE_SIZE) # 通常 4096 MEM_KB=$(grep MemTotal /proc/meminfo | awk '{print $2}') SHMMAX=$(( MEM_KB * 1024 / 2 )) # 取物理内存一半 SHMALL=$(( SHMMAX / PAGE + 1 )) # 换算成页数 echo "kernel.shmmax = $SHMMAX" echo "kernel.shmall = $SHMALL"

手册里 shmmax 给的是 4294967295(约 4G),shmall 给的是 2097152,按 4K 页算对应 8G,比 shmmax 大了一倍,这是允许的——shmall 只要不小于 shmmax 除以页大小就行。反过来如果 shmall 小于这个值,实例启动会直接抛 ORA-27102,而且报错信息里不会告诉你哪个参数错了。所以我一般按上面的脚本算完再留 20% 余量,而不是死抄。

net.ipv4.ip_local_port_range给到 9000 到 65500,是为了把低位端口让出来给 SCAN、VIP 和监听,避免客户端连接和本地临时端口撞车。rmem/wmem那四项是网络缓冲区大小,RAC 的节点间心跳和数据传输走私有网络,调大一点在高并发下能少丢包。改完执行sysctl --system而不是sysctl -p,前者会加载/etc/sysctl.d/下所有文件并按文件名排序,后者只读/etc/sysctl.conf,这是两回事。

3.4 CVU 与 cvuqdisk:装前检查的最后一关

cluster verification utility(CVU)是安装前最后一轮体检,能提前发现 80% 的环境问题。它依赖一个叫 cvuqdisk 的小 RPM,位置在 Grid 安装介质的cv/rpm目录下,必须在所有节点上都装:

cd /u01/soft/grid/cv/rpm export CVUQDISK_GRP=oinstall rpm -ivh cvuqdisk-1.0.10-1.rpm cd /u01/soft/grid ./runcluvfy.sh stage -pre crsinst -fixup -n node1,node2 -verbose

CVUQDISK_GRP这个环境变量如果不设,包会装到 root 组下,后续 CVU 以 grid 用户跑的时候读不到磁盘信息,报的错还很绕。-fixup参数会让 CVU 尝试自动修复它能修的问题(比如缺包、参数不对),但修不了网络和存储配置,别指望它包治百病。-n后面跟所有节点的主机名,必须和/etc/hosts里写的一致,大小写、短名长名都要统一。

输出结尾出现Pre-check for cluster services setup was successful才算过。如果卡在某一项,别急着往下走,/tmp/CVU_*目录下有exectask的完整输出,比屏幕上的摘要详细得多。

4. 网络、GNS 与 UDEV 绑盘:让 SCAN、VIP 和 ASM 盘名一次对齐

4.1 五类地址的规划:先画表再动手

RAC 的网络是整份手册里最容易配错的部分,因为地址类型多、约束多。先把规划表列清楚:

类型数量是否固定解析方式说明
Public IP每节点 1 个固定绑网卡/etc/hosts主机名,字母数字加连字符
VIP每节点 1 个可不绑网卡,但必须能解析/etc/hosts 或 GNS18c 起可全配或全不配
Private IP每节点 1 到 4 个固定绑网卡/etc/hosts 或 GNS超过 4 个自动做冗余
SCAN VIP3 个不绑网卡DNS 或 GNS必须同子网
GNS VIP1 个不绑网卡/etc/hosts只有用 GNS 才需要

几条硬约束:命名只能用字母、数字和连字符,下划线是绝对禁止的,用了以后监听注册会失败;Public、VIP、SCAN VIP 必须在同一个子网段,私有网络单独一个网段;私有网卡不需要做 bond,集群自己会用 HAIP 做高可用,配了 bond 反而可能干扰;VIP 从 18c 开始支持「全部节点都配」或「全部节点都不配」,但不支持只给部分节点配,这条手册里专门标了。

4.2 hosts 与 BIND 正解域

纯手工方案下,所有地址都写/etc/hosts,SCAN 单独交给 DNS。下面是两节点示例,域名用rac.demo:

# /etc/hosts 192.168.204.11 pub19-node1.rac.demo pub19-node1 192.168.204.12 pub19-node2.rac.demo pub19-node2 40.40.40.41 priv19-node1.rac.demo priv19-node1 40.40.40.42 priv19-node2.rac.demo priv19-node2 192.168.204.21 vip19-node1.rac.demo vip19-node1 192.168.204.22 vip19-node2.rac.demo vip19-node2 192.168.204.10 gns19-vip.rac.demo gns19-vip

每个地址后面跟一个短名,Grid 安装时如果只认短名,长名解析不到就会报「PRVF-4664」。hosts 写完后用ping -c1和getent hosts双向验证一遍。

DNS 部分用 BIND,装包后先写主配置:

# /etc/named.conf(只列关键段落) options { directory "/var/named"; allow-query { any; }; recursion yes; allow-transfer { none; }; }; zone "rac.demo" IN { type master; file "named.rac.demo"; }; zone "204.168.192.in-addr.arpa" IN { type master; file "named.192.168.204"; }; zone "40.40.40.in-addr.arpa" IN { type master; file "named.40.40.40"; };

allow-query生产上应限制成集群网段,测试环境图省事写 any 也能跑。反解域名的写法是把网段倒过来加.in-addr.arpa,192.168.204 网段对应204.168.192.in-addr.arpa,私有网段同理。正解文件内容:

$TTL 600 @ IN SOA rac.demo. admin.rac.demo. ( 2024061201 ; serial 1D ; refresh 1H ; retry 1W ; expire 3H ) ; minimum @ IN NS master.rac.demo. master <p> <a href="https://download.csdn.net/download/jwocnimabi/12237038" style="color:#ec7500;font-size:14px;"> 本文还有配套的精品资源,点击获取 </a> <img alt="menu-r.4af5f7ec.gif" src="https://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif" style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;"> </p>
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进