很多DBA和架构师第一次接触Oracle 19C RAC时,都会栽在同一个地方:文档读了一堆,命令抄了一堆,但脑子里始终没有一张完整的图——这个进程到底在哪个节点上跑?这个数据块为什么从节点1跑到了节点2?心跳断了之后集群到底先做了什么?
我自己的经验是,与其痛苦地啃完几百页官方手册,不如先把架构图画出来。所以去年我给自己定了一个硬任务:用41张架构图,把Oracle 19C RAC的原理完完整整拆一遍。拆完之后,很多之前靠死记硬背的知识点突然自己串起来了。这篇文章就是把那41张图的拆解逻辑和关键知识点做一个系统整理,适合刚从单机向集群过渡的DBA、要负责RAC规划与运维的工程师,以及准备RAC相关认证和面试的人。
1. 为什么用“架构图”而不是“官方文档”来学RAC
1.1 文字资料和官方文档的认知漏斗问题
官方文档当然最权威,但RAC的知识体系实在太庞杂了:集群件、ASM、监听、网络、OCR、Voting Disk、Cache Fusion、GES/GCS,每一块单独拿出来都是一本书。如果按文档的顺序从第一章线性读到最后一章,前脚读完卷I后脚就忘了卷II,因为它们之间是网状关系,不是线性关系。
架构图恰恰能把网状关系摊平成一面墙。你看一张图,能同时看到组件的位置、连接线、依赖方向和故障传递路径。文字需要用五百字描述清楚的关系,图上一根箭头就解决了。
我自己更偏好的做法是“先图后文”。先通过架构图建立位置感——知道每个组件住在哪一层、和谁相邻、数据往哪个方向走,再针对感兴趣的局部去查文档。这样文档不再是天书,而是一本你带着问题去翻的参考手册。
1.2 41张图不是随手画的,背后有一张分类地图
41这个数字不是随便定的。我是把RAC的整个知识体系拆成了8条线,每条线再按认知深度拆成具体图。这样既能保证知识没有死角,又不至于陷入细节出不来。
| 图集编号 | 分类方向 | 核心内容 | 对应图数 |
|---|---|---|---|
| 01~05 | 集群总体架构 | 单实例vs RAC、RAC整体拓扑、GI组件组成 | 5张 |
| 06~12 | 共享存储与ASM | OCR、Voting Disk、ASM实例架构、磁盘组冗余 | 7张 |
| 13~19 | 全局资源管理 | GCS、GES、缓存融合、锁模式、GRD目录 | 7张 |
| 20~26 | 网络与连接管理 | 公私网分离、VIP、SCAN、监听器、连接过程 | 7张 |
| 27~32 | 集群生命周期 | 启动顺序、资源注册、节点加入、节点驱逐、脑裂判定 | 6张 |
| 33~36 | 备份恢复与容灾 | RMAN、ASM备份、实例恢复、ADG叠加 | 4张 |
| 37~39 | 性能与排障 | 常见等待事件、cache fusion定位、日志排查链路 | 3张 |
| 40~41 | 升级变更与运维 | 19c升级路径、日常维护命令图谱 | 2张 |
这个划分不是死的,你可以按自己的职责增减。比如你做纯运维,性能那三张可以扩成十张;你做架构设计,缓存融合那几张必须整明白。关键是每一张图都要能回答一个问题,而不是为了凑数量。
1.3 看图学习也要分阶段:图像化理解、结构记忆、故障反推
拿到一张图,不同阶段的人看到的深度完全不一样。我自己归纳了三个阶段。
第一阶段是图像化理解。你盯着图,能把每个方块和连线的名称念出来,能大概说出它是干什么的。比如看到HAS进程,知道它是Host Agent Service,负责单机资源管理。这个阶段不要贪多,先把图看熟。
第二阶段是结构记忆。合上图,你能自己动手把这张图重新画出来。注意,这一步非常重要,因为“能看懂”和“能画出来”差距极大。我当时练图的时候,每张图都至少手画过三遍,画不出来就回去看图,直到不看原图能画到八分像为止。
第三阶段是故障反推。拿到一个故障现象,比如“节点2被驱逐了”,你脑子里要能弹出一张图:心跳超时 -> CSS判定脑裂 -> 投票盘仲裁 -> 节点2被移除 -> 资源迁移到节点1。如果这个链条你脑子里能自动播放,说明这张图已经内化成你的知识了。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 从单实例到RAC集群:先建立起整体架构图
2.1 RAC不是把数据库从一台机器复制到两台
这是最容易产生的误解。很多刚从单机转RAC的DBA会觉得,RAC就是把同一个数据文件放到两台服务器上,然后各跑一个实例去读写。如果真这么理解,后面遇到的所有问题——为什么数据文件不能同时写?为什么会有锁竞争?为什么一个节点挂了另一个节点要做恢复?——全都解释不清。
RAC的本质是“多实例共享一套数据文件”。这里的关键词是“共享”。数据文件不是复制两份分别给两个实例用,而是物理上只有一份,两个实例通过高速网络和分布式缓存机制去读写同一份数据。换句话说,RAC解决的是“让更多CPU和内存参与处理同一个数据库的工作负载”的问题,不是“数据多副本”的问题。
所以第一张架构图就应该画清楚这个对比:左边是单实例,一个实例对一个数据库;右边是双实例RAC,两个实例通过内部连接访问同一套存储。这张图能帮你理解后面所有机制存在的原因——为什么需要分布式锁?因为两个实例都要写同一张表;为什么需要缓存融合?因为节点1要读节点2缓存里的数据块,不能每次都去硬盘。
2.2 GI集群件、ASM、数据库实例三者的分工
Oracle 19C RAC的软件栈可以分成三层,你一定要在第二张图里把它们画成三个明确的层。
最底层是操作系统,Linux通常需要额外的内核参数、用户组、目录权限配置。但RAC真正的基础设施是从GI(Grid Infrastructure)开始的。GI是Oracle集群技术的总入口,里面包含了集群件Clusterware、ASM、监听器等一大堆组件。注意,19c里建议用统一的GI家目录,ASM实例也是由GI统一管理的。
中间层是ASM(Automatic Storage Management)。它不是传统意义上的文件系统,而是Oracle自带的卷管理器加文件系统。ASM实例和数据库实例不一样,它没有逻辑数据库的概念,主要职责是管理磁盘组、维护文件信息的分布、处理IO。数据库实例产生的数据文件、控制文件、日志文件都放在ASM磁盘组里。
最上层才是真正的数据库实例。你通过sqlplus / as sysdba连上的其实只是这个实例,实例有SGA、有后台进程,和单实例数据库的结构类似。
三者的启动顺序是:先起操作系统 -> 起GI(含ASM)-> 起数据库实例。配置crsctl管理的资源里,能看到类似ora.asm、ora.<db>.db、ora.<db>.taf等资源,它们之间有明确的依赖关系。你在图上要把这条串起来画成一条纵向的依赖链,以后排查启动故障时会特别有用。
2.3 OCR与Voting Disk:集群的“记忆”和“投票权”
OCR(Oracle Cluster Registry)和Voting Disk是RAC里两个最容易被搞混的组件。我之前带新人时经常问一句话:节点重启,你怎么知道集群里都有哪些资源?答案就在OCR里。
OCR就像一个集群的“记忆中枢”。它保存了集群的配置信息——节点列表、ASM磁盘组信息、资源清单、监听器配置。没有OCR,集群不知道有哪些资源需要启动,也不知道资源之间的依赖关系。OCR默认存放在ASM磁盘组里,通常建议单独一个磁盘组存放。损坏了可以用ocrconfig -restore从自动备份恢复,所以日常备份策略千万别漏了OCR。
Voting Disk则完全不同。它的作用是在集群发生脑裂时进行投票仲裁,决定哪个分区保留、哪个节点被驱逐。19c中Voting Disk默认也存放于ASM磁盘组,最少需要3个 Vote Disk(奇数)才能形成多数。但简单说就是:OCR管“集群长什么样”,Voting Disk管“出问题时谁说了算”。
在架构图上,我会把OCR和Voting Disk画在ASM层旁边,分别用“配置文件中心”和“仲裁表决器”来标注。这两个东西不画清楚,后面理解节点驱逐机制会很吃力。
3. 缓存融合与全局资源协调:RAC最核心也最抽象的一张图
3.1 Cache Fusion到底解决什么问题
RAC里所有实例共享同一份数据文件,但每个实例都有自己的SGA和缓冲区缓存(Buffer Cache)。假设节点1要更新某一行数据,而这一行正好被节点2的会话读取过,数据块缓存在节点2的内存里。那节点1该怎么办?
最笨的方案是:节点1去请求节点2把脏数据写回磁盘,写完之后再从磁盘读进自己的Buffer Cache。这种“数据落地再重读”的方式叫“Disk Fusion”,性能极差——一次数据块交互要经过内存、日志文件、磁盘、再读进内存整条链路。
Cache Fusion的思想是:既然节点2内存里有这个块,干脆通过内部私有网络直接把它传给节点1。数据块从节点2的Buffer Cache复制到节点1的Buffer Cache,不需要写磁盘。同理,如果节点1只是需要以共享模式读这个块,它和节点2可以同时持有共享锁,大家一起用内存中的副本,谁都不用落盘。
这就是RAC高性能的核心。所有被传过来的数据块走的是专用心跳网络,所以私网延迟和带宽几乎是RAC性能的生命线。这张图你画透了,就明白了为什么RAC对私网要求那么苛刻——它承载的不是心跳那么简单,还有实时数据块的传输。
3.2 数据块从节点A到节点B的完整链路
这一部分我建议画一张时序图,把图上的每一步都附上对应的后台进程名,不然会感觉是空中楼阁。
假设节点A上的会话要更新节点B缓存里的数据块:
- 节点A的会话发出更新请求,DBWn先不管,先由Server Process在本地Buffer Cache里找块,没找到。
- 节点A的LMS(Lock Manager Server)进程向全局资源目录GRD(Global Resource Directory)查询这个块当前由谁持有。
- 节点A的LMS通过私网向节点B的LMS发起请求,请求的内容包括:申请该块的当前版本。
- 节点B的LMS拿到请求后,结合本地Buffer Cache状态,通过私网把块传输给节点A,同时更新GRD中的资源状态:块的主节点变成了节点A。
- 节点A的LMS把块写入本地Buffer Cache,通知Server Process可以继续执行更新。
这个过程要特别注意一点:节点A拿到块的时候,如果节点B手上是脏块(已被修改但尚未写盘),节点B会先在内存中生成一个一致性副本(CR副本)再传过来,同时还会在本地记录下相关的重做信息。所以Cache Fusion是内存到内存的操作,但它绕不开日志。
画完这张图你再看AWR报告里的gc cr block transfer、gc buffer busy这类等待事件,就能自动联系上具体是哪一步出现了瓶颈——是私网带宽不够、GRD锁冲突频繁,还是慢速存储导致缓冲区刷新不及时。
3.3 GCS、GES、LMS的角色不能搞混
在RAC的全局资源管理里,有三个名词经常被一起提到。我把它们各自的职责固定在一张图上。
GCS(Global Cache Service)管的是数据块的访问协调,回答的问题是“这个块现在在谁的内存里”。GES(Global Enqueue Service)管的是非数据块资源的同步,比如表锁、事务锁、字典锁。你可以粗略理解成数据层面的协调归GCS管,锁和队列层面的协调归GES管。LMS进程是GCS的核心执行者,LMD进程负责GES的锁管理通信。在19c中,LMS默认进程数可以通过参数gcs_server_processes控制。
画图时我会把三个角色画成三层:数据块访问申请 -> GCS/LMS处理;普通锁/队列申请 -> GES/LMD处理;两者的状态都记录在共享的GRD中。这样当你看到某个阻塞等待事件时,第一反应就是先判断它归属哪条线,不会拿着锁的问题跑到GCS那边找原因。
4. RAC网络架构:VIP、SCAN、心跳网络的一整套逻辑
4.1 公网和私网为什么必须分开
很多RAC初学者会问,既然服务器有万兆网卡,一条物理网线全搞定不就行了?理论能通,但实际运维中你会被自己坑死。
公网和私网承载的流量性质完全不同。公网承载的是应用连接、远程sqlplus、备份任务等外部访问流量;私网承载的是集群心跳、缓存融合数据块、锁消息等内部同步流量。如果把两者混在一起,一个突发的大量SQL查询会瞬间占满带宽,导致私网心跳超时,进而引发节点驱逐。你想象一下:一个节点因为“心跳没收到”被集群踢出去,查日志发现原因竟然是同事跑了个全表扫描把网络带宽吃光了——这场景在混布网络里真的很常见。
19c对私网和公网的核心要求是:物理隔离、互不干扰。心跳要绑定独立网卡,而且心跳网卡通常建议绑定成Bond模式,避免单网卡故障引发脑裂。你需要用oifcfg iflist和oifcfg getif查看网络接口配置,确认集群识别到的网络和你规划的完全一致。
4.2 一个透明故障转移的载体:VIP
VIP(Virtual IP,虚拟IP)是RAC对外提供服务的重要设计。每个节点除了有一个真实公网IP,还有一个VIP。VIP随节点启动而绑定在指定网卡上,当节点宕机,VIP会自动漂移到幸存的节点上。
为什么需要VIP?关键在连接管理。客户端的连接如果是通过真实IP建立的,节点挂了之后,TCP连接会一直等待超时,直到几十分钟后彻底断掉。但如果连接的是VIP,节点宕机后VIP漂移到其他节点,内核会立即向客户端发送一个RST包,把坏连接立刻断开。应用层看到的是“连接瞬间中断”,而不是长期假死,这样就能快速触发重连逻辑,把请求转发到存活节点。
在架构图上,我会在公网层画出每个节点的真实IP和VIP,并用箭头表示VIP漂移方向。注意一个关键细节:如果RAC启用了SCAN,客户端通常不会直接连VIP,而是连SCAN IP,由监听器来分配VIP背后的真实实例。
4.3 SCAN IP的工作机制与常见误区
SCAN(Single Client Access Name)是RAC对外提供统一入口的VIP机制。集群会配置一个域名,对应2~3个SCAN IP,它们同样有漂移能力。客户端只需要连接SCAN IP,不需要关心集群现在有几个节点、哪个节点还活着。
具体工作机制是:客户端发起连接到SCAN IP -> SCAN监听器接收连接 -> 根据负载策略,把连接转发给目标节点的本地监听器 -> 本地监听器建立到实际实例的连接。
这里有个经典误区:很多人以为SCAN IP只有一个,所以SCAN是单点。其实SCAN IP通常配置3个,由DNS轮询或GNS解析到多个IP,任何一个挂了都不影响连接入口。如果你在部署时发现某一条SCAN IP不通,先查DNS解析是否把SCAN域名同时解析到了所有SCAN IP,再查监听器状态。
4.4 一个典型的心跳故障排查故事
之前处理过一个场景,节点2反复被驱逐,每次都是偶发性的,查crsd日志也看不到明确报错,只有“connect timed out”。当时第一反应是私网有问题,但检查网卡和交换机都正常。
后来用ping -f连续压测心跳IP,发现延迟能飙到几百毫秒甚至丢包。继续排查,发现私网交换机的某个端口被配置成了半双工模式,和服务器网卡的自动协商结果不一致,底层大流量时产生大量冲突重传。把端口改成强制千兆全双工后,节点再也没有被驱逐过。
这个故事告诉我们,画完网络架构图之后,别只看它静态的样子,要能想象出“链路质量变差”时整张图会发生什么变化。架构图不仅是知识梳理工具,也是故障排查的事故现场还原工具。
5. 用架构图还原故障场景:脑裂、节点驱逐与启动恢复
5.1 脑裂的判定逻辑:为什么不简单地“少数服从多数”
RAC集群里每个节点通过心跳互相监控。如果私网异常,某些节点可能互相看不到对方,但每个节点都认为自己才是健康的,都想继续对外提供服务,这就出现了脑裂。
Oracle解决脑裂的方式是Voting Disk投票机制。每个节点的CSSD进程会定期向Voting Disk写入信息,脑裂发生时各节点通过心跳无法达成一致,就向Voting Disk发起投票,得票超过半数的节点分区可以存活,不到半数的节点会被驱逐。
因为Voting Disk要求奇数个,就是为了制造“多数”的概念。如果只有2个Voting Disk,两个节点各得1票,平局无法裁决;3个Voting Disk则一定能分出一个多数。
这里有一个容易忽略的点:整个集群的节点数如果是偶数,Voting Disk的设计会配合一个“节点数权重”的机制,但19c里最常见推荐的还是奇数个Voting Disk和奇数个节点,尽量避免平局场景。
5.2 节点驱逐完整过程:每一步都值得画出来
节点驱逐(Node Eviction)是RAC运维里最惊心动魄的场景之一,你可以把它画成一条六步流程:
- 节点B的CSSD发现节点A心跳超时,超过
misscount阈值。 - 节点B发起重新配置(Reconfig),各节点进入投票流程。
- 在Voting Disk仲裁后,少数派节点(比如节点A)被判为失败。
- 节点A被强制重启,或者通过
reboot方式拉起,目的是清掉节点A上可能残留的锁和进程。 - 幸存的节点B、C重新配置集群状态,接管节点A上的服务和资源。
- 节点A重启完成后重新加入集群,依赖的资源恢复在线。
在这张图里,最容易出错的是第4步。节点被驱逐后不是“不干活就行”,而是必须彻底重启,保证内存里没有任何残留的锁状态。如果节点A拒绝重启,集群可能会反复发起驱逐,直到节点A完全离线。
实际运维时,你用crsctl status res -t看资源状态,经常能看到某资源处于INTERMEDIATE或者OFFLINE状态,然后用crsctl gettype确认节点类型后再决定是failover还是重新加入集群。这些都是围绕这张流程图的实操细节。
5.3 排障时日志的阅读顺序
架构图画清楚了,排障才不会被日志淹死。我自己处理RAC节点驱逐类问题时,通常按这个顺序看日志:
- 第一站:
/var/log/messages(或journalctl),看操作系统的OOM、网卡down、磁盘IO错误等底层硬件信号。 - 第二站:
crsctl check cluster和crsctl stat res -t,看集群资产的状态和资源分布。 - 第三站:GI诊断日志,
$GI_HOME/log/<hostname>/cssd/ocssd.log和crsd/crsd.log,这是集群决策的产生地。 - 第四站:ASM实例的alert日志,判断是否是ASM/存储故障间接导致节点被驱逐。
- 第五站:数据库实例的alert日志,看被驱逐前后数据库内的等待事件和异常记录。
只要按这条链路走下去,大多数故障的根因都会在每一站的日志中露出马脚。
6. 动手画出自己的41张图:工具、方法与知识内化
6.1 绘制工具的选型建议
画架构图的工具很多,我自己的要求只有两点:一是能快速拖拽出方框和连线,二是方便后续修改。常用的有draw.io(开源免费,支持markdown里嵌SVG导出)、ProcessOn(在线协作,适合团队共用)、Excalidraw(更像手绘风格,不追求像素级对齐的时候我很喜欢)。Visio当然也可以,但和Linux服务器的风格总觉得不太搭。
如果画的图最终要放到知识库或团队Wiki里,我建议统一用draw.io,因为它可以直接存储为xml文件,方便版本管理。团队协作时,每个人用自己的分支改图,合并时也不会像二进制图片那样冲突。
6.2 画图时的几个个人方法
第一,先画全局,再画局部。不要一开始就死磕某一台服务器的进程,先把所有节点、网络、存储画出来,再逐层细化。
第二,图中一定要画出“数据流”和“控制流”。方框和连线只是静态结构,真正体现原理的是箭头上的标识。同一根线上,数据流和控制流用不同颜色区分,看图时一下就能明白谁在传数据、谁在发指令。
第三,标注异常路径。比如心跳正常情况下是低流量,心跳超时后就变成驱逐流程;缓存融合正常状态下是块直接传输,失败后会有CR副本重读。一次画图时把这些异常分支也画上去,图才会越用越厚。
第四,加命令标注。每个资源旁边推荐写上常用的排查命令。比如OCR边上标注ocrcheck,ASM磁盘组旁边标注asmcmd lsdg。这样架构图就不仅仅是一张原理图,还是一个排障命令索引。
6.3 如何把图转化为团队的知识资产
图画完之后,最大的价值其实是讲出来。给团队做一次内部培训,每讲一张图就相当于把这张图重新验证了一遍。画图过程中可能有些地方你是糊的,一旦被迫给别人讲清楚,你就会发现自己哪个环节没吃透。
我自己的习惯是每周抽两个晚上,每次只精讲三张图。讲之前先自己快速复现一遍,讲的时候对照图展开,遇到不能立即解释清楚的细节就标注为课后作业。几周下来,整个团队对RAC的认知水平会提升非常明显。
另外,可以把这些架构图整理成一份“RAC排障手册”,每张图对应一个常见的运维场景。比如“节点启动后资源起不来”对应看crsd日志;“客户端连接风暴导致监听器异常”对应看监听日志和OS资源。这样的手册不是用Word堆出来的,而是以图为核心串联起来的,查起来效率极高。
学RAC这件事,最容易陷入的误区就是追求“把所有命令都背下来”。命令可以查文档,但底层机制必须靠理解。而我目前试下来最高效的理解方式就是画图——先把大框架画出来,再往里填细节,最后用故障场景去验证图对不对。
如果你准备自己画一版,我的建议是别贪多,先从“单实例vs RAC整体拓扑”这张图开始,画透一张再画下一张。等第41张图收笔的时候,你对Oracle 19C RAC的掌控感,一定和现在完全不同。
