接手一套 Oracle 19c RAC 环境之后,最怕的不是节点挂掉,而是不知道它什么时候、在哪个环节先出的问题。RAC 的本质是多个节点共享一套数据库,节点之间的心跳、集群服务、监听、ASM 卷组任何一个环节出了状况,都会让整个集群变得不可用。而排障时如果东敲一条命令西查一个日志,往往越查越乱,最后连问题出在哪个层面都说不清楚。
这篇东西想解决的问题很明确:怎么在最短时间内判定一套 19c RAC 多节点环境到底健不健康,以及出问题时按什么顺序、用哪些命令快速定位。这份指南适合经常接触 RAC 的 DBA、刚接手 19c 集群的运维同学,也适合那些需要给客户做应急响应的人。我会把实际排查时最常用的命令、输出判读方法、容易忽略的细节和踩过的坑整理出来,按固定套路执行,五分钟内基本能判断出集群状态。
1. RAC 运行状态排查的整体思路
1.1 为什么需要一套固定的排查路径
RAC 环境里涉及的组件太多了。一套 19c RAC 至少包含 GI(Grid Infrastructure)层面的集群软件、两个节点上的数据库实例、SCAN 监听和节点监听、ASM 实例与磁盘组、OCR 和 Voting Disk,还有公网、私网两套网络。任何一个组件出问题,症状都可能表现为"应用报错连不上""某个节点 down 了""数据库卡顿"这类模糊现象。
如果每次都是凭感觉从某一个现象开始查,很容易陷入一个误区:花大量时间在某个组件上排查,结果发现根因在另一个层面。比如应用一直报连接超时,你可能先去查监听,查了半天发现监听正常,最后才发现是某个节点被驱逐出了集群,服务没有漂移过去。这种问题我在生产环境见过不止一次。固定的排查路径本质上是一条覆盖所有关键组件的检查链路,按顺序走一遍,任何一层有问题都会暴露出来。
用一个生活化的类比:体检。你不会因为嗓子疼就直接去做胃镜,而是先量体温、看血常规、再根据指标异常去查具体器官。RAC 排查也是一样,先看整体,再逐层深入。这份指南的核心就是给你一套"体检项目表"。
1.2 一次完整排查需要覆盖的五个层面
我习惯把一次完整的 RAC 运行状态排查拆成五个层面,每个层面都有对应的一组命令。这五个层面按依赖关系排列:集群层在最底层,实例层在上面,然后是服务和监听,接着是存储层,最后用日志来验证和佐证判断。
| 层面 | 核心内容 | 关键命令 |
|---|---|---|
| 集群层 | CRS 进程、节点成员关系、资源状态 | crsctl check cluster -all、crsctl status resource -t |
| 实例层 | 各节点实例是否 open、会话情况 | srvctl status database、v$instance |
| 服务与监听层 | SCAN、节点监听、服务状态 | srvctl status listener、lsnrctl status |
| 存储层 | ASM 实例、磁盘组空间与冗余 | asmcmd lsdg、v$asm_diskgroup |
| 日志层 | alert 日志、CRS 日志、监听日志 | 各组件日志文件,用于交叉验证 |
这五层不是孤立的。比如实例起不来,可能是 ASM 磁盘组不可用;监听起不来,可能是 OCR 里注册的资源状态不对。所以排查时必须带着"上一层的结果会影响下一层"的思路,而不是机械地跑命令。
2. 五分钟快速体检命令集
2.1 用 crsctl 快速确认集群整体状态
所有 RAC 排查的第一步,一定是确认集群服务本身是否健康。crsctl check cluster -all会在所有节点上执行健康检查并返回每个节点的状态。正常输出的结尾一般是CRS-4537: Cluster Ready Services are healthy之类的结果,如果某个节点异常,会直接显示CRS-4535: Cannot communicate with Cluster Ready Services或类似报错。
这个命令只给结果,不给出细节。所以第二步要执行crsctl status resource -t,把集群里所有资源的在线状态列出来。正常环境下,ora.rac.db、ora.asm、ora.node1.vip、ora.scan1.vip、ora.listener 这些资源的 STATE 都是 ONLINE,且分布在对应的节点上。如果有资源显示 OFFLINE、INTERMEDIATE 或 UNKNOWN,就要看具体是哪个资源、属于哪个节点。
提示:
crsctl status resource -t的输出里,TARGET 列显示期望状态,STATE 列显示实际状态。如果 TARGET 是 ONLINE 但 STATE 是 OFFLINE,说明资源没有正常启动;如果两边都是 OFFLINE,可能是被人为 stop 了。这两者有本质区别。
我在实际巡检时有个习惯:先跑crsctl check cluster -all,如果全部 healthy,再跑crsctl status resource -t快速扫一遍资源状态。如果第一步就有节点报错,直接进入对应节点的日志排查,不用浪费时间去逐条看资源。
2.2 数据库实例状态检查
集群健康不代表数据库实例健康。19c RAC 环境下,每个节点上都有一个实例,任何一个实例 down 掉,都会让客户端连接和负载分配出问题。检查实例状态最直接的方式是srvctl status database -d <dbname> -v,输出会列出每个实例所在的节点、状态和角色。
举个例子:
$ srvctl status database -d orcl -v Instance orcl1 is running on node node1, instance state: Open Instance orcl2 is running on node node2, instance state: Open如果看到 instance state 是 Started 而不是 Open,说明实例进程起来了但数据库没有完成 mount 或 open,这通常意味着存储或控制文件有问题。如果某个节点没有实例输出,说明这个节点上根本没起实例,需要检查实例进程或 GI 资源。
用 SQL 查看也是常见做法。登录任意一个节点,查询select inst_id, instance_name, status, host_name from gv$instance order by inst_id;,可以一次看全所有实例状态。status列显示OPEN说明实例正常,显示STARTED或MOUNTED说明处于中间状态。
2.3 监听与 SCAN 监听状态
应用连不上 RAC,一半以上的根因在监听层面。19c RAC 环境有节点监听和 SCAN 监听两类。节点监听负责本机实例的本地连接,SCAN 监听配合 SCAN VIP 实现客户端负载均衡和故障转移。
检查命令是srvctl status listener,它会同时列出所有监听资源及其状态。之后用lsnrctl status <监听名>查看单个监听的详细情况,包括服务注册列表、实例数量、当前连接数。正常状态下,lsnrctl status里能看到每个实例的多个服务名注册,比如orclXDB、orcl这些服务都有对应的实例在监听器注册表里。
注意:如果
lsnrctl status显示 "The listener supports no services" 或者服务列表为空,不代表监听本身挂了,而是实例没有完成向监听的动态注册。常见原因包括 LOCAL_LISTENER/REMOTE_LISTENER 参数配置错误、网络不通、监听日志权限问题。这种状态最坑,因为监听进程是活的,但应用就是连不上。
2.4 ASM 实例与磁盘组状态
RAC 的数据文件、控制文件、参数文件基本都在 ASM 里,ASM 状态直接决定数据库能不能正常读写。检查 ASM 常用两个入口:一个是用 SQL 查v$asm_diskgroup,另一个是进入 ASM 命令环境用asmcmd lsdg。
asmcmd lsdg输出里,最重要的是 State、Type 和 Usable_file_MB 三列。State 栏显示MOUNTED表示磁盘组已挂载;Type 显示NORMAL、HIGH或EXTERNAL代表冗余级别;Usable_file_MB 是扣除冗余之后实际可用的空间。如果某个磁盘组显示DISMOUNTED,那数据库大概率已经出问题了。
另外要关注磁盘组空间使用率。ASM 磁盘组空间用完时,数据库会直接报 ORA-15041,严重时所有写入都会失败。巡检时如果发现某个磁盘组使用率超过 85%,就要提前规划扩容或清理,别等到报错再处理。
2.5 关键日志位置与命名规律
排查 RAC 运行状态,最终都要落到日志上。19c 的日志路径比早期版本更有规律,都在$ORACLE_BASE/diag目录下。常用日志的位置如下:
- 数据库实例 alert 日志:
$ORACLE_BASE/diag/rdbms/<dbname>/<SID>/trace/alert_<SID>.log - ASM 实例 alert 日志:
$ORACLE_BASE/diag/asm/+asm/+ASM1/trace/alert_+ASM1.log - CRS 日志目录:
$GRID_HOME/log/<hostname>/,下面有 crsd.log、cssd.log、evmd.log - 监听日志:
$ORACLE_BASE/diag/tnslsnr/<hostname>/<listener>/alert/log.xml或按listener_XXXX的监听日志目录
这些日志的命名规律是固定的。多个节点之间日志格式一致,排查时可以并行对比。后续的排障中,这几个日志文件是核心证据来源,后面的章节会展开讲怎么高效读它们。
3. 核心状态视图与排查细节
3.1 实例状态视图的进阶用法
gv$instance和v$instance是最常用的两个视图,但它们能看的东西差别不小。v$instance只显示当前登录实例的信息,gv$instance聚合了所有实例的信息。在一个节点上执行gv$instance查询,就可以确认每个实例是否都起来了、版本是否一致、当前 SCIN 是否一样。
除了gv$instance,还有几个视图值得关注。gv$active_instances显示当前参与集群工作的实例列表,gv$services可以看每个服务在每个实例上的状态。多节点环境排查时,我最常做的一件事是同时查这几个视图,把实例、服务、节点对应关系全部拉出来:
select inst_id, instance_name, status, host_name, version, logins from gv$instance order by inst_id; select inst_id, name, name_id, active from gv$active_instances order by inst_id; select inst_id, name, pdb, failover_type, goal from gv$services order by inst_id, name;如果gv$instance里有实例状态不是 OPEN,或者gv$active_instances里少了某个节点,基本可以确定该节点的实例有问题。此时去对应的 alert 日志查 ORA- 错误,是最高效的路径。
3.2 OCR 与 Voting Disk 的健康确认
OCR 和 Voting Disk 是集群的"大脑"和"选票箱"。OCR 存集群配置信息,Voting Disk 负责节点成员仲裁。这两个组件出问题时,集群可能频繁驱逐节点,或者干脆起不来。
检查 OCR 的命令是ocrcheck,正常输出会显示 OCR 文件、Device、Status 为 AVAILABLE,且 Total size 和 Used size 都在正常范围。如果出现PROT-601或者 Status 不是 AVAILABLE,OCR 完整性有问题,需要从自动备份中恢复。
检查 Voting Disk 用crsctl query css votedisk。正常输出会列出所有 voting disk 的路径和状态,且状态都是 ONLINE。如果某个 voting disk 显示 OFFLINE 或缺失,说明该磁盘有问题。需要注意的是,19c 环境下 voting disk 放在 ASM 磁盘组里,查询命令会显示类似+DATA的路径。
提示:不要轻易在集群正常运行时删除或添加 voting disk。每次变更后必须验证磁盘组冗余级别,否则一旦某块盘故障,整个集群可能全部停机。这个操作我建议只在维护窗口做,并且前后都要执行
crsctl query css votedisk确认。
3.3 服务状态与应用连接排查
RAC 环境通常按业务配置多个服务(Service),比如核心交易走oltp_svc,报表走report_svc。服务状态直接决定应用能不能正常工作。检查命令是srvctl status service -d <dbname>。
输出示例:
$ srvctl status service -d orcl Service oltp_svc is running on instance(s): orcl1, orcl2 Service report_svc is running on instance(s): orcl1 Service offlinesvc is not running.如果某个服务应该运行在两个实例上,实际只在其中一个运行,说明另一个实例上该服务注册失败。这时候要看服务的srvctl config service -d <dbname> -s <服务名>配置,以及实例上的监听注册情况。
应用连接排查还要关注 SCAN 的解析情况。客户端连接 RAC 通常用scan-name:1521/orcl这种方式,SCAN 解析到多个 SCAN VIP 实现负载均衡。排查连接问题时,在客户端执行tnsping <scan名称>,确认能够解析到所有 SCAN IP,再确认监听有没有正常提供服务。如果发现 SCAN 只解析到一个 IP,说明 SCAN 监听资源有问题或 DNS 配了多个 A 记录但没有轮询。
3.4 会话、锁和负载角度
运行状态排查不只是看进程起没起来,还要看数据库能不能正常处理负载。多节点环境里,一个节点的会话数异常或者某个节点出现了锁等待,都会影响整体可用性。
用gv$session查看节点分布和活动会话:
select inst_id, count(*), sum(decode(status, 'ACTIVE', 1, 0)) active_cnt from gv$session group by inst_id order by inst_id;正常情况下每个节点的会话数应该大致均衡。如果某个节点的活动会话数异常高,另一个节点几乎没有,除了连接配置问题,也可能和某个节点的硬件性能、网络状况有关,需要进一步排查。
锁相关的排查用gv$lock和gv$session_wait。当应用报"资源忙"或卡死时,先查有没有阻塞会话:
select blocking_session, sid, serial#, inst_id, event, wait_class, seconds_in_wait from gv$session where blocking_session is not null order by seconds_in_wait desc;阻塞查询的event通常是enq: TX - row lock contention或library cache lock这类,拿到阻塞链之后,定位源头会话并评估是否可以 kill。RAC 环境下这种锁问题往往跨节点,因为一个节点的会话可能被另一个节点的会话阻塞,单查本地v$session会漏掉信息,所以必须用gv$视图。
4. 常见问题与排查技巧实录
4.1 节点被驱逐出集群的问题
RAC 里最典型的故障就是节点被驱逐(Node Eviction)。症状是某个节点上的实例和资源全部 offline,另外的节点正常。造成驱逐的原因通常有三类:心跳网络中断、存储 IO 长时间 hang、节点时钟漂移。
排查这种问题,第一步先确认集群目前的状态,用crsctl status resource -t看哪些节点的资源 offline。第二步看被驱逐节点上的crsd.log和cssd.log,重点找Node eviction、LOST CONNECTION、IO latency、clock之类的关键字。第三步检查私网网卡状态、心跳链路的连通性和丢包率。
时钟漂移是一个容易被忽略的原因。RAC 集群要求所有节点时间同步,一般用 NTP 或 chrony。如果某个节点时钟跑偏超过几十毫秒,就可能触发驱逐。我在一次生产故障里遇到过,节点一切正常,但每过几天就被踢出集群一次,最后发现是 chrony 配置被某台新机器覆盖了。用timedatectl和chronyc tracking检查时间同步状态,是排查这个问题的标准动作。
4.2 监听异常但集群看起来正常
有一种故障特别容易误导人:crsctl status resource -t显示监听资源 ONLINE,lsnrctl status显示监听进程活着,但应用就是连不上。这种情况十有八九是监听器服务注册列表异常,或者监听日志文件被撑爆。
先看监听日志。19c 默认的监听日志目录在$ORACLE_BASE/diag/tnslsnr/<hostname>/listener/alert/log.xml,如果磁盘空间满了或者日志文件损坏,监听会拒绝新连接但不影响已有连接。另外检查监听端口是否被占用的经典命令是netstat -anp | grep 1521,确认监听确实在监听预期的地址。
还有一种情况是 hosts 文件解析问题。RAC 环境里/etc/hosts必须正确配置所有节点的公网和私网地址,如果私网主机名解析到错误地址,节点间的监听注册就会出现奇怪现象。这类问题排查到最后,往往是简单因素:某个节点的 hosts 文件被改动了。
4.3 实例启动失败与 ORA- 错误定位
实例起不来是 RAC 排障的另一大类问题。常见错误包括 ORA-01157(数据文件无法识别)、ORA-15081(ASM 磁盘组未挂载)、ORA-29701(集群无法识别实例)等。
定位这类问题的步骤很有规律:先用srvctl start instance -d <dbname> -i <实例名>尝试启动,然后立刻去查该实例的 alert 日志尾部。alert 日志会记录启动过程中遇到的第一个致命错误,这个错误往往就是根因。比如 ORA-01157 后面通常会紧跟着 ORA-01110,明确指出是哪个数据文件有问题。
另一种情况是实例已经被注册到集群里,但启动时由于参数文件位置不对起不来。19c RAC 常用 spfile 放在 ASM 里,如果 ASM 磁盘组没挂载,spfile 读取失败,实例就起不来。此时先去查 ASM 的 alert 日志确认磁盘组状态,再回头处理数据库实例。
4.4 日志交叉验证技巧
单独看一个日志经常不够,我习惯把实例 alert 日志、ASM alert 日志和 crsd 日志按时间线对齐看。比如实例报 ORA-15081 可能是 ASM 实例先挂了导致的,那 ASM 日志里会有关键的错误记录;而 ASM 挂掉可能又是磁盘组里某块盘坏了,这在v$asm_disk里能查到。三层日志对时间戳,很容易把因果链拼完整。
日志文件都很大,直接用编辑器打开搜很费劲。我常用的命令:
# 查看实例 alert 日志最后 200 行,重点是行首有 *** 分隔块的最后一次内容 tail -200 $ORACLE_BASE/diag/rdbms/<dbname>/<SID>/trace/alert_<SID>.log # 按时间过滤某段日志,通常用前一天 20:00 到当前时间 awk '/2026-04-06 20:00/,/2026-04-07 08:00/' alert_<SID>.log # 搜索包含 ORA- 的行 grep -n "ORA-" alert_<SID>.log | tail -30还有一个实用技巧:alert 日志里以***开头的分隔块代表一次事件,比如实例启动、shutdown、错误记录。用grep -n "^\*\*\*" alert_<SID>.log | tail -10可以快速找到最近的几次关键事件,再定位到对应时间块细看,效率比从头翻到尾高很多。
5. 实操笔记:一套可落地的巡检与应急脚本
5.1 每日巡检命令组合
与其每天手动敲一遍命令,不如把稳定的检查项写成脚本。我在生产环境用的巡检思路很简单:按集群、实例、监听、ASM 四个维度,把命令串起来,输出重定向到文件,再用颜色区分正常和异常。
一段简化的核心命令组合如下:
GRID_HOME=/u01/app/19.0.0/grid ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1 DB_NAME=orcl # 1. 集群状态 $GRID_HOME/bin/crsctl check cluster -all # 2. 资源状态 $GRID_HOME/bin/crsctl status resource -t # 3. 数据库实例 $GRID_HOME/bin/srvctl status database -d $DB_NAME -v # 4. 监听状态 $GRID_HOME/bin/srvctl status listener # 5. ASM 磁盘组空间 $ORACLE_HOME/bin/sqlplus -s / as sysasm <<EOF set lines 200 col name format a15 col state format a10 col type format a10 select name, state, type, usable_file_mb, total_mb from v\$asm_diskgroup; exit EOF # 6. OCR 检查 $GRID_HOME/bin/ocrcheck把这段脚本放到所有节点上,用 cron 每天定时执行并输出到/tmp/rac_check_$(hostname).log。第二天上班扫一眼各节点的输出,重点关注有没有OFFLINE、ERROR、FAILED这类字眼。这套逻辑很基础,但确实能防住绝大多数"小问题拖成大故障"的场景。
5.2 应急排障的执行顺序
如果脚本输出异常,或者应用已经报障,排障顺序要遵循"从底层到上层、先集群后实例"的原则。我总结了一套四步走的应急套路:
- 先看集群成员:
crsctl check cluster -all,确认所有节点在线。如果节点被驱逐,立刻定位驱逐原因,而不是急着把实例拉起来。 - 再看资源状态:
crsctl status resource -t,找出异常的资源。重点关注数据库、监听、VIP、ASM 这几类关键资源。 - 然后看实例与日志:如果数据库资源异常,查
srvctl status database和对应实例的 alert 日志;如果监听资源异常,查监听状态和监听日志。 - 最后看存储:
asmcmd lsdg确认磁盘组挂载和空间,因为存储层面是很多实例故障的下游根本原因。
这四步走完,绝大多数问题能定位到具体组件。剩下的是跨组件的复杂问题,比如网络波动导致的心跳丢失、存储路径问题导致的 IO hang,这些就需要结合系统层的dmesg、网络日志、存储告警做进一步交叉验证了。
提示:应急排障时切忌反复重启。很多 DBA 看到节点 down 就
crsctl stop cluster -all然后重新 start,结果重复触发相同的故障。合理做法是:先采集日志证据,确认根因后再恢复。除非是明显的进程僵死,否则"先取证、后恢复"是生产环境排障的底线原则。
最后再分享一点个人体会
我在生产环境折腾 RAC 排障这几年,最大的感受是:RAC 出故障不可怕,可怕的是没有一套固定的排查逻辑。很多时候,问题之所以拖成事故,是因为排查的人在不同的节点、不同的日志、不同的工具之间来回跳,信息越看越乱。把这套"集群层 → 实例层 → 监听层 → 存储层 → 日志层"的顺序跑熟,遇到任何 RAC 运行状态异常,心里都会有一个清晰的路线图。
另外,日常巡检的人一定不要只盯着crsctl status resource -t这个单一输出。它确实是最快的入口,但 ASM 磁盘组空间、监听服务注册列表、实例 alert 日志里的隐性错误,这些"慢变量"才是一套 RAC 能否长期稳定运行的关键。把这套五分钟体检变成肌肉记忆,你的 19c RAC 环境就能多一分确定性。