系列:Oracle 数据库全栈运维实战系列(VMware 版)· 高可用篇(核心篇)
版本:Oracle Grid Infrastructure 19.3 + Oracle Database 19.3,RHEL/Oracle Linux 7.9
环境:VMware Workstation 16/17 双节点虚拟机,共享 VMDK 实现共享存储
一、为什么在 VMware 上装 RAC?
生产环境 RAC 通常跑在物理机 + 专有存储(SAN/iSCSI)上,门槛高。而VMware 虚拟化可以把共享存储“模拟”出来——两台虚拟机挂载同一块 VMDK,即可让 Oracle 集群软件(Grid Infrastructure)感知到真实共享盘,从而跑起完整、真实的双节点 RAC 集群:
- 真实集群组件:CRS / CSS / EVM / ASM / SCAN 全部可用
- 可验证 Cache Fusion、DLM(分布式锁管理)、GV$ 视图等 RAC 核心机制
- 单台物理机即可模拟两节点,适合学习、开发、测试与灾备演练
注意:容器化(Docker)方案只能“近似”模拟,VMware 方案与生产环境完全同构,迁移到物理机/云上的 RAC 几乎无差异。
二、环境规划
2.1 硬件与软件
| 项 | 配置 |
|---|---|
| 宿主机 | 物理机,内存 ≥ 16G(推荐 32G),磁盘 ≥ 200G |
| 虚拟化 | VMware Workstation 16/17 Pro |
| 节点 | rac1 / rac2,各分配4 vCPU / 8GB 内存 / 80G 系统盘(Oracle Linux 7.9) |
| 共享盘 | 独立 VMDK 文件,两节点同时挂载 |
| 数据库 | Oracle Grid 19.3 + Oracle DB 19.3(linuxx64_193000) |
| ASM | CRSDG(3×2G,放 OCR/Voting)+ DATADG(数据盘 20G+) |
2.2 网络规划(每节点 2 张网卡)
| 用途 | 网段 | rac1 | rac2 |
|---|---|---|---|
| Public(业务) | 192.168.10.0/24 | 192.168.10.173 | 192.168.10.174 |
| Private(心跳) | 172.16.0.0/24 | 172.16.0.158 | 172.16.0.159 |
| VIP | 192.168.10.0/24 | 192.168.10.175 | 192.168.10.176 |
| SCAN | 192.168.10.0/24 | 192.168.10.177~179(3 个地址) | — |
VMware 中:Public 网卡用 NAT/桥接,Private 网卡用“仅主机模式(Host-Only)”,确保两节点心跳互通且独立。
三、第一步:创建共享磁盘
3.1 用 vmware-vdiskmanager 预创建共享 VMDK
在宿主机上(VMware 安装目录,Windows)执行:
set pa th=%path%;C:\Program Files (x86)\VMware\VMware Workstation vmware-vdiskmanager.exe -c -s 2g -a lsilogic -t 4 "D:\VMS\Storages ac-crs1.vmdk" vmware-vdiskmanager.exe -c -s 2g -a lsilogic -t 4 "D:\VMS\Storages ac-crs2.vmdk" vmware-vdiskmanager.exe -c -s 2g -a lsilogic -t 4 "D:\VMS\Storages ac-crs3.vmdk" vmware-vdiskmanager.exe -c -s 20g -a lsilogic -t 4 "D:\VMS\Storages ac-data.vmdk"
-t 4= 预分配(EagerZeroedThick),共享盘必须预分配;-a lsilogic指定控制器类型,与后续 vmx 一致。
3.2 在两台虚拟机 vmx 中挂载共享盘
编辑rac1.vmx 和 rac2.vmx(两个文件都要加,指向同一 VMDK):
# ===== 共享磁盘段(两节点必须一致) ===== disk.locking = "false" diskLib.dataCacheMaxSize = "0" diskLib.dataCacheMaxReadAheadSize = "0" diskLib.dataCacheMinReadAheadSize = "0" diskLib.dataCachePageSize = "4096" diskLib.maxUnsyncedWrites = "0" scsi1.present = "TRUE" scsi1.virtualDev = "lsilogic" scsi1.sharedBus = "virtual" scsi1:0.present = "TRUE" scsi1:0.fileName = "D:\VMS\Storages ac-crs1.vmdk" scsi1:0.mode = "independent-persistent" scsi1:0.redo = "" scsi1:1.present = "TRUE" scsi1:1.fileName = "D:\VMS\Storages ac-crs2.vmdk" scsi1:1.mode = "independent-persistent" scsi1:1.redo = "" scsi1:2.present = "TRUE" scsi1:2.fileName = "D:\VMS\Storages ac-crs3.vmdk" scsi1:2.mode = "independent-persistent" scsi1:2.redo = "" scsi1:3.present = "TRUE" scsi1:3.fileName = "D:\VMS\Storages ac-data.vmdk" scsi1:3.mode = "independent-persistent" scsi1:3.redo = ""关键点:
disk.locking = "false":允许两虚拟机并发写同一 VMDKscsi1.sharedBus = "virtual":共享 SCSI 总线mode = "independent-persistent":共享盘不能用快照模式
VMware Workstation GUI 里“硬盘 → 高级 → SCSI 控制器共享”选择“虚拟”也可配置;直接改 vmx 更可靠。
四、第二步:系统基础配置(两节点相同)
4.1 /etc/hosts(Public + Private + VIP + SCAN)
127.0.0.1 localhost localhost.localdomain # Public 192.168.10.173 rac1.example.com rac1 192.168.10.174 rac2.example.com rac2 # Private(心跳) 172.16.0.158 rac1-priv.example.com rac1-priv 172.16.0.159 rac2-priv.example.com rac2-priv # VIP 192.168.10.175 rac1-vip.example.com rac1-vip 192.168.10.176 rac2-vip.example.com rac2-vip # SCAN 192.168.10.177 rac-scan.example.com rac-scan 192.168.10.178 rac-scan.example.com rac-scan 192.168.10.179 rac-scan.example.com rac-scan若用 DNS 解析 SCAN,可只写一条;测试环境直接写 hosts 最省事(3 个地址都指向同一域名做轮询)。
4.2 关闭 SELinux / 防火墙 / NetworkManager 干扰
sed-i's/^SELINUX=.*/SELINUX=disabled/'/etc/selinux/config systemctl stop firewalld&&systemctl disable firewalld systemctl disable NetworkManager# 用 network 脚本管理(可选,仅测试环境)reboot4.3 内核参数(/etc/sysctl.d/97-oracle.conf)
cat>/etc/sysctl.d/97-oracle.conf<<'EOF' fs.aio-max-nr = 3145728 fs.file-max = 6815744 kernel.shmmax = 68719476736 # 按内存调整(8G 内存可设 64G 上限) kernel.shmall = 16777216 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 net.ipv4.tcp_rmem = 4096 87380 4194304 net.ipv4.tcp_wmem = 4096 16384 4194304 kernel.panic_on_oops = 1 vm.min_free_kbytes = 524288 EOFsysctl--system4.4 资源限制(/etc/security/limits.d/99-grid-oracle.conf)
cat>/etc/security/limits.d/99-grid-oracle.conf<<'EOF' oracle soft nproc 16384 oracle hard nproc 16384 oracle soft nofile 1024 oracle hard nofile 65536 oracle soft stack 10240 oracle hard stack 32768 oracle hard memlock 68719476736 grid soft nproc 16384 grid hard nproc 16384 grid soft nofile 1024 grid hard nofile 65536 grid soft stack 10240 grid hard stack 32768 grid hard memlock 68719476736 EOF4.5 关闭透明大页 + 扩大 /dev/shm
# 修改 /etc/default/grub,在 GRUB_CMDLINE_LINUX 加:# numa=off transparent_hugepage=nevergrub2-mkconfig-o/boot/grub2/grub.cfg# /dev/shm 扩到 2Gecho"tmpfs /dev/shm tmpfs defaults,rw,exec,size=2G 0 0">>/etc/fstabmount-oremount,size=2G /dev/shm4.6 创建用户、组与目录
groupadd-g54321oinstallgroupadd-g54322dbagroupadd-g54323opergroupadd-g54324backupdbagroupadd-g54325dgdbagroupadd-g54326kmdbagroupadd-g54327asmdbagroupadd-g54328asmopergroupadd-g54329asmadminuseradd-u1100-goinstall-Gdba,oper,backupdba,dgdba,kmdba griduseradd-u1101-goi nstall-Gdba,oper,backupdba,dgdba,kmdba,asmdba oraclemkdir-p/u01/app/19.0.0/gridmkdir-p/u01/app/oraclemkdir-p/u01/app/gridchown-Rgrid:oinstall /u01/app/19.0.0 /u01/app/gridchown-Roracle:oinstall /u01/app/oraclechmod-R775/u014.7 SSH 双机互信
# 在 rac1 上执行(grid 与 oracle 用户都要配)su- grid ssh-keygen-trsa-P''-f~/.ssh/id_rsacat~/.ssh/id_rsa.pub>>~/.ssh/authorized_keysssh-oStrictHostKeyChecking=no rac2"cat ~/.ssh/id_rsa.pub">>~/.ssh/authorized_keys# 互相验证(两边都要能免密)sshrac2date五、第三步:磁盘分区与 udev 固定设备名
5.1 分区(两节点共享盘同样可见,只在 rac1 分区即可,2 节点重扫)
echo-e"n\np\n1\n\n\nw"|fdisk/dev/sdbecho-e"n\np\n1\n\n\nw"|fdisk/dev/sdcecho-e"n\np\n1\n\n\nw"|fdisk/dev/sddecho-e"n\np\n1\n\n\nw"|fdisk/dev/sde partprobe5.2 udev 规则(把磁盘固化为 asm 设备名)
先获取每块盘 WWID:
/usr/lib/udev/scsi_id--whitelisted--replace-whitespace--device=/dev/sdb1再把结果写入/etc/udev/rules.d/99-oracle-asmdevices.rules:
KERNEL=="sd*", SUBSYSTEM=="block", PROGRAM=="/usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/$name", RESULT=="<sdb1的WWID>", SYMLINK+="oracleasm/asm-crs1", OWNER="grid", GROUP="asmadmin", MODE="0660" KERNEL=="sd*", SUBSYSTEM=="block", PROGRAM=="/usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/$name", RESULT=="<sdc1的WWID>", SYMLINK+="oracleasm/asm-crs2", OWNER="grid", GROUP="asmadmin" , MODE="0660" KERNEL=="sd*", SUBSYSTEM=="block", PROGRAM=="/usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/$name", RESULT=="<sdd1的WWID>", SYMLINK+="oracleasm/asm-crs3", OWNER="grid", GROUP="asmadmin", MODE="0660" KERNEL=="sd*", SUBSYSTEM=="block", PROGRAM=="/usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/$name", RESULT=="<sde1的WWID>", SYMLINK+="oracleasm/asm-data", OWNER="grid", GROUP="asmadmin", MODE="0660"加载规则并验证:
udevadm control --reload-rules udevadm trigger--type=devices--action=changels-l/dev/oracleasm/# 应看到 asm-crs1/2/3、asm-data 4 个符号链接,属主 grid:asmadmin六、第四步:安装 Grid Infrastructure(Cluster 软件)
6.1 解压软件并装 cvuqdisk
unzip-qoLINUX.X64_193000_grid_home.zip-d/u01/app/19.0.0/gridchown-Rgrid:oinstall /u01/app/19.0.0/gridcd/u01/app/19.0.0/grid/cv/rpmrpm-ivhcvuqdisk-1.0.10-1.rpm6.2 预检查(可选但推荐)
su- grid /u01/app/19.0.0/grid/runcluvfy.sh stage-precrsinst-nrac1,rac2-fixup-verbose6.3 静默安装 GI(响应文件 gridsetup.rsp)
su- gridcat>/home/grid/gridsetup.rsp<<'EOF' oracle.install.responseFileVersion=/oracle/install/rspfmt_crsinstall_response_schema_v19.0.0 oracle.install.option=CRS_CONFIG oracle.install.asm.OSDBA=asmdba oracle.install.asm.OSOPER=asmoper oracle.install.asm.OSASM=asmadmin 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.ClusterConfiguration=STANDALONE oracle.install.crs.config.configureAsExtendedCluster=false oracle.install.crs.config.clusterName=rac-cluster oracle.install.crs.config.gpnp.configureGNS=false oracle.install.crs.config.autoConfigureClusterNodeVIP=false oracle.install.crs.config.clusterNodes=rac1:rac1-vip:HUB,rac2:rac2-vip:HUB oracle.install.crs.config.networkInterfaceList=ens33:192.168.10.0:1,ens37:172.16.0.0:5 oracle.install.crs.configureGIMR=false oracle.install.asm.diskGroup.name=CRSDG oracle.install.asm.diskGroup.redundancy=NORMAL oracle.install.asm.diskGroup.AUSize=4 oracle.install.asm.diskGroup.disks=/dev/oracleasm/asm-crs1,/dev/oracleasm/asm-crs2,/dev/oracleasm/asm-crs3 oracle.install.asm.diskGroup.diskDiscoveryString=/dev/oracleasm/* oracle.install.asm.SYSASMPassword=Your_ASM_Password oracle.install.asm.monitorPassword=Your_ASM_Password EOF/u01/app/19.0.0/grid/gridSetup.sh-silent-responseFile/home/grid/gridsetup.rsp-ignorePrereqnetworkInterfaceList 中网卡名(ens33/ens37)按实际环境调整;
-ignorePrereq用于跳过不影响核心的预检告警(测试环境)。
6.4 执行 root 脚本(关键步骤!)
安装接近完成时,按提示在两个节点分别以 root 执行:
# rac1/u01/app/19.0.0/grid/root.sh# rac2(rac1 执行完后再执行)/u01/app/19.0.0/grid/root.sh6.5 验证集群
su- grid crsctlstatres-t# 预期:ora.cssd / ora.diskmon / ora.asm / ora.crsd 等均为 ONLINE crsctl check cluster-allcrsctl check crs七、第五步:安装数据库软件 + DBCA 建 RAC 库
7.1 安装 Database 软件
unzip-qoLINUX.X64_193000_db_home.zip-d/u01/app/oracle/product/19.0.0/dbhome_1chown-Roracle:oinstall /u01/app/oraclesu- oraclecd/u01/app/oracle/product/19.0.0/dbhome_1 ./runInstaller-silent-responseFile<db_install.rsp>oracle.install.option=INSTALL_DB_SWONLYUNIX_GROUP_NAME=oinstallINVENTORY_LOCATION=/u01/app/oraInventoryORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1ORACLE_BASE=/u01/app/oracleoracle.install.db.InstallEdition=EEoracle.install.db.OSDBA_GROUP=dbaoracle.install.db.OSOPER_GROUP=operoracle.install.db.OSBACKUPDBA_GROUP=backupdbaoracle.install.db.OSDGDBA_GROUP=dgdbaoracle.install.db.OSKMDBA_GROUP=kmdbaoracle.install.db.OSRACDBA_GROUP=dbaoracle.install.db.CLUSTER_NODES=rac1,rac2oracle.install.db.config.starterdb.type=GENERAL_PURPOSEoracle.install.db.config.starterdb.globalDBName=orcloracle.install.db.config.starterdb.SID=orcloracle.install.db.config.starterdb.characterSet=AL32UTF8oracle.install.db.config.starterdb.memoryOption=falseoracle.install.db.config.starterdb.storageType=ASM_STORAGE# 两节点执行 root 脚本/u01/app/oracle/product/19.0.0/dbhome_1/root.sh# rac1 与 rac2 各执行一次7.2 DBCA 创建 RAC 数据库
su- oracle dbca-silent-createDatabase-templateName General_Purpose.dbc-gdbnameorcl-sidorcl-characterSetAL32UTF8-sysPasswordYour_DB_Password-systemPasswordYour_DB_Password-storageTypeASM-diskGroupNameDATADG-datafileDestination'+DATADG'-recoveryAreaDestination'+DATADG'-totalMemory4096-nodeinforac1,rac2若尚未创建 DATADG,可先在 ASM 里补建:
asmca图形界面或asmcmd/SQL 创建。
八、第六步:验证 RAC 集群
-- 1. 集群资源crsctl stat res-t-- 2. 实例状态(两实例都应为 OPEN)srvctlstatusdatabase-d orcl-- 3. GV$ 视图验证(RAC 专属!)SQL>SELECTinst_id,instance_name,statusFROMgv$instance;-- 4. Cache Fusion 相关等待事件(RAC 特有)SQL>SELECTevent,total_waitsFROMgv$system_eventWHEREeventLIKE'gc%'ANDrownum<=10;-- 5. SCAN 连接验证(负载均衡)sqlplus system/xxx@rac-scan:1521/orcl-- 反复连接观察实例轮换(SELECT inst_id FROM gv$instance)验证通过标准:
crsctl stat res -t全部 ONLINEgv$instance返回 2 行(两实例)- SCAN 连接自动在两节点间负载均衡
九、踩坑记录(重点收藏)
| # | 坑 | 现象 | 解决 |
|---|---|---|---|
| 1 | 共享盘未预分配 | GI 预检报共享存储权限/一致性错误 | vmdk 用-t 4预分配,两节点 vmx 配置完全一致 |
| 2 | 忘记disk.locking=false | 第二节点看不到共享盘/IO 错误 | vmx 加共享段配置,重启虚拟机 |
| 3 | hosts 有误 | 集群节点间通信失败,cssd 起不来 | VIP/SCAN 地址不能与 Public 重复;私网名后缀 -priv |
| 4 | 透明大页未关 | GI 预检 WARN/性能异常 | grub 加transparent_hugepage=never并重建引导 |
| 5 | /dev/shm 过小 | 共享内存不足报错 | fstab 扩到 2G 并 remount |
| 6 | udev WWID 不一致 | 两节点看到的盘名不同 | 共享盘两节点 WWID 必须一致(同一 VMDK);分别核对 |
| 7 | root.sh 顺序 | rac2 root. | |
| sh 报错 | 必须 rac1 先执行成功后再执行 rac2 | ||
| 8 | 心跳网卡选错 | 集群误把 Public 当心跳 | networkInterfaceList 里 Private 网卡类型填 5(cluster_interconnect) |
| 9 | SCAN 解析失败 | 客户端连不上 SCAN | hosts 里 SCAN 域名 3 个地址都写,或配 DNS 轮询 |
| 10 | 内存不足 | root.sh/GI 安装 OOM | 每节点至少 8G 内存,别同时跑太多进程 |
十、结语
在 VMware 上部署 RAC,与生产环境(物理机 + SAN)流程完全一致:共享存储 → 系统加固 → GI → DB → DBCA → 验证。这套环境的每个组件都是真实的,后续可以继续做:
- Data Guard:在 RAC 基础上搭建容灾(系列第 14 篇)
- 监控:Prometheus/Grafana 采集 GV$ 指标(系列第 17 篇)
- 故障演练:模拟节点宕机,验证 Failover(系列第 20 篇)
本文章属于《Oracle 数据库全栈运维实战系列(VMware 版)》高可用篇。系列规划见专栏总纲,欢迎收藏、交流。