☰
Oracle 19c RAC状态排查指南:从集群到实例的快速定位实战
2026/10/6 3:41:00 网站建设 项目流程

1. RAC运行状态排查的底层逻辑

1.1 多节点"运行状态"究竟包含哪几层

Oracle 19c RAC(Real Application Clusters)的核心价值就是把多个节点的实例、资源、存储组合成一个对外提供连续服务的数据库系统。但"多节点运行状态"这句话,在运维层面其实拆成了至少三个独立层级:第一层是集群层(Clusterware),负责节点成员关系、VIP、SCAN、OCR与表决盘这些"基础设施";第二层是实例层(Database Instance),也就是每个节点上的Oracle进程、SGA、后台进程和监听器;第三层是应用层,也就是客户端能不能正常连上、会话和负载是不是均衡分布。很多DBA排查时习惯一头扎进SQL里看等待事件,结果节点本身已经被集群驱逐了,或者监听器早就挂了,这种单点视角是RAC排查里最致命的误区。

我在生产环境里见过太多类似的场面:业务反馈某个节点上的应用特别慢,开发直接甩过来一句"是不是RAC有问题"。但实际查下来,数据库实例状态是OPEN的,ASM实例也正常,最后发现是监听器的某个服务注册失效,连接全部被路由到了另一个节点。这类问题如果只看数据库层面,永远找不到根因。所以排查RAC运行状态,第一步不是打开任何工具,而是先建立"分层排查"的思维框架。

1.2 排查思路:从整体到局部,从实例到集群

我自己总结的排查顺序一直是一个"从外到内、从轻到重"的漏斗:先用最快的手段(通常是SQL)把多个节点的实例状态拉一个总览,确认数据库层有没有节点掉线;如果数据库层正常,再回到集群层检查CRS管理的各类资源是否有OFFLINE、UNKNOWN状态;最后才深入到日志、监听、ASM磁盘组甚至网络心跳这些细节。这个顺序的好处是快,能在三分钟内把问题圈定到某一层,而不是拿着几十条命令挨个试。

排查动作本身也要讲究"最简"。所谓最简排查指南,不是让你少做检查,而是把高频、高价值、低误报的检查项收敛成一套固定动作。比如实例是否在线、集群资源是否在线、监听是否注册,这三件事基本覆盖了90%的日常"节点状态异常"反馈。剩下10%的疑难问题,再按日志路径去追,也完全来得及。这篇总结就是按这个思路展开的,每一条命令和视图都来自我在19c环境里的实际验证,直接照着敲即可。

2. 工具弹药库:19c RAC状态排查必知命令与视图

2.1 集群层:crsctl 与 ocrcheck

集群层的核心工具是crsctl,它是对接Oracle Clusterware(GI,Grid Infrastructure)的官方命令行入口。19c里最常用的三条子命令分别是:

# 检查所有节点上的集群关键进程是否在线 crsctl check cluster -all # 查看CRS资源(含数据库、监听、VIP、SCAN、ASM)的详细状态 crsctl status resource -t # 以别名方式快速看数据库与ASM的在线状态 crsctl status resource ora.database.type

crsctl check cluster -all会在每个节点上执行一次健康检查,逐个报告CRS-4535(在线)或CRS-4536(离线)这样的输出。我习惯先跑这条,它能快速区分"整集群异常"和"单节点异常"。如果某个节点返回CRS-4537(节点不可达),基本就能断定是心跳或节点本身的问题,后面再细查。

ocrcheck是检查OCR(Oracle Cluster Registry)完整性的工具,输出里重点看Total bytes allocated、Total bytes used和Integrity check这几项。生产上我见过OCR损坏导致集群资源无法上线的案例,表现为ocrcheck报 "PROT-601" 之类错误。这里提醒一点:OCR的物理备份按惯例要放到节点本地的/u01/app/ocrbackup之类目录,别只依赖ASM里的冗余。

2.2 实例层:gv$ 视图家族

RAC环境里,凡是需要看"所有节点"的视图,一定要用带gv$前缀的版本,而不是v$。v$instance只能反映你当前连接的这一个实例,gv$instance才能列出全部节点。这个区别在RAC排查里是高频考点,也是很多新手踩坑的地方。

-- 查看RAC所有节点的实例状态概览 SELECT inst_id, instance_name, status, database_status, active_state, startup_time, last_archive_time FROM gv$instance ORDER BY inst_id;

这条SQL是整篇文章的核心动作之一,字段含义后面会细讲。此外,gv$session、gv$active_session_history、gv$sqlarea这类视图在排查"某个节点慢"时价值极高。比如怀疑节点2的负载异常,可以直接:

SELECT inst_id, COUNT(*), ROUND(AVG(last_call_et), 2) FROM gv$session WHERE status = 'ACTIVE' GROUP BY inst_id;

用inst_id做分组字段,一眼就能看出活动会话是不是集中到了某个节点。

2.3 监听与连接层:lsnrctl 与 tnsping

监听器是客户端连接的第一道关卡,也是RAC排查里最常被忽略的一环。19c的监听默认服务名在$ORACLE_HOME/network/admin/listener.ora里配置,端口通常是1521。检查监听状态用:

# 查看监听服务状态,含已注册的服务名 lsnrctl status LISTENER # 查看监听日志位置,用于排查连接失败 lsnrctl show log_file LISTENER

lsnrctl status输出里最关键的部分是 "Services Summary" 下面的每个服务名及其实例数。如果数据库传入参数配置了remote_listener或local_listener,这里会体现出"服务在哪个节点、有几个实例可用"。只有当服务名对应的实例数等于正常节点数时,负载均衡和故障切换才有基础。如果只有一个实例,另一个节点的监听大概率没注册上。

连接层验证用tnsping和实际SQL连接双保险。tnsping只验证网络连通性和监听是否应答,不验证数据库实例是否可登录:

tnsping ora19c # ora19c 是tnsnames.ora里的服务别名

2.4 日志定位:alert log 与集群日志

状态排查最终都要落到日志上。19c RAC的日志分成三条线:数据库实例日志(alert_<sid>.log)、ASM实例日志(alert_+ASM1.log)和集群日志($ORACLE_HOME/log/<hostname>/alert<hostname>.log以及 crsd、cssd、evmd 这些守护进程各自的日志)。很多DBA排查时只盯着数据库日志,忽略了集群日志,结果节点被驱逐、资源重启这类事件怎么查都查不到根源。

一条可以快速定位日志路径的SQL:

-- 查出实例的DIAGNOSTIC_DEST,日志就在该目录下的diag/rdbms/<dbname>/<sid>/trace/alert_<sid>.log SELECT name, value FROM v$parameter WHERE name = 'diagnostic_dest';

集群日志的默认根目录是$GI_HOME/log/<hostname>,里面按crsd、cssd、evmd、agent个子目录存放。重点看crsd/crsd.log和cssd/cssd.log。比如节点被驱逐,cssd.log里会明确记录心跳丢失、misscount达到阈值、本地节点被踢出集群的过程,时间点精确到毫秒,跟应用侧反馈的"断连时间"对得上,就能形成完整证据链。

3. 三分钟快速体检:一条SQL判断所有节点健康状况

3.1 "一页纸"状态总览SQL

先给结论。我在19c RAC生产环境里日常巡检,第一件事就是用这条SQL把全部节点的状态压在一页纸里:

SELECT inst_id, instance_name, status, database_status, active_state, TO_CHAR(startup_time, 'YYYY-MM-DD HH24:MI:SS') AS startup_time, ROUND((SYSDATE - startup_time) * 24, 2) AS uptime_hours, NVL(TRIM(TO_CHAR(SYSDATE - last_archive_time)), 'NO-ARCH') AS last_arch FROM gv$instance ORDER BY inst_id;

输出一般长这样:

INST_IDINSTANCE_NAMESTATUSDATABASE_STATUSACTIVE_STATESTARTUP_TIMEUPTIME_HOURSLAST_ARCH
1orcl1OPENACTIVENORMAL2026-04-01 09:12:0096.032026-04-05 08:58:11
2orcl2OPENACTIVENORMAL2026-04-01 09:12:0096.032026-04-05 08:58:12

判读规则:STATUS必须是OPEN,DATABASE_STATUS必须是ACTIVE,ACTIVE_STATE在正常状态下是NORMAL。UPTIME_HOURS对比各节点启动时间是否一致,如果一个节点的数值明显小于其他节点,说明它近期发生过重启。LAST_ARCH如果显示NO-ARCH,表示归档停滞,通常是归档目的地(比如ASM磁盘组或FRA区)出问题,这种问题不解决,日志迟早会堆积把节点拖垮。

3.2 判读关键指标:启动时间、状态字段中的隐藏信息

startup_time是判断"节点是否悄悄重启过"的最硬核证据。生产环境里经常有这种情况:夜间没有业务窗口,但节点因为内存压力、进程异常被系统OOM Killer干掉,或者因为HAVIP漂移导致实例重启,早上业务高峰才发现连接全部堆到一个节点。如果所有节点startup_time完全一致,基本能排除近期重启,问题重点转移到连接层或性能层。

database_status的取值除了ACTIVE,还有SUSPENDED。出现SUSPENDED通常是罕见的内部错误或者正在执行某种恢复操作,需要立刻查看 alert 日志确认有没有 ORA-600 之类的内部错误。active_state取DRAINING时也要小心,这代表实例正处于隔离排空状态,正在把服务切换给其他节点,此时该节点不会接收新连接。

还有一个小细节:gv$instance.instance_name的命名规则是ORCL1、ORCL2这种格式,它对应$ORACLE_SID,而db_unique_name是集群层面的数据库唯一名。两者别搞混,排查时如果设置的ORACLE_SID不对,连接的是哪个实例都搞不清楚。

3.3 快速定位异常节点的筛选逻辑

总览SQL找到异常节点后,需要立刻定位是"实例问题"还是"服务问题"。我习惯做的第二个动作是看活动会话分布:

SELECT inst_id, status, COUNT(*) AS session_count, ROUND(AVG(last_call_et), 2) AS avg_last_call_sec, MAX(last_call_et) AS max_last_call_sec FROM gv$session WHERE username IS NOT NULL GROUP BY inst_id, status ORDER BY inst_id, status;

正常情况下,两个节点的活动会话占比应该和业务负载成正比。如果节点1有大量INACTIVE会话堆积,而节点2几乎没有,再看一下连接是否被某个应用固定路由到了节点1。如果某个节点的max_last_call_sec数值特别大,比如几千秒甚至上万秒,说明存在卡住的会话,要用gv$session结合gv$sql去抓 SQL_ID,再通过blocking_session去查锁等待。

另外一个非常实用的Trick:通过gv$active_instances或gv$services确认服务名在哪些节点上可用。

SELECT name, inst_id, status, enabled FROM gv$services ORDER BY name, inst_id;

如果某个服务只在节点1显示ENABLED,节点2完全消失,那问题往往出在监听注册或service_registration相关配置上,而不是实例本身。这条线索能帮你把排查方向从"数据库内核"切换到"网络与监听",效率会高非常多。

4. 实例级深度排查实操

4.1 实例状态与会话级体检

总览SQL确认实例OPEN之后,如果还是觉得"节点不对劲",就要进入实例级深度检查。我先说一个最容易被忽略的动作:检查gv$instance里的logins列。它有两种取值:ALLOWED和RESTRICTED。出现RESTRICTED说明实例被人工设置成了维护模式,新连接会被拒掉,但已有的连接还能继续跑。这种状态经常是运维改动遗留,比如:

ALTER SYSTEM ENABLE RESTRICTED SESSION;

执行过之后忘了关掉,业务就会反馈"某个节点的连接一直建不上"。排查时看到LOGINS=RESTRICTED,直接恢复:

ALTER SYSTEM DISABLE RESTRICTED SESSION;

接下来看会话和等待。19c里gv$session_wait已经逐步被gv$session中的 wait 相关字段取代,但gv$session_wait_history仍然很有用。我个人排障顺序是:先用gv$session找EVENT不为空、WAIT_CLASS != 'Idle'的会话,然后去gv$active_session_history里看这些会话在过去一小时内的等待事件分布。如果log file sync占大头,说明有提交特别频繁的应用;如果是enq: TX - row lock contention,那就是锁竞争,要按BLOCKING_SESSION逐层往上游找锁的持有者。

-- 查看RAC所有节点当前非空闲等待的会话 SELECT inst_id, sid, serial#, username, sql_id, event, wait_class, seconds_in_wait AS wait_secs FROM gv$session WHERE wait_class != 'Idle' ORDER BY seconds_in_wait DESC;

4.2 ASM实例与磁盘组状态

19c RAC通常由ASM管理数据文件、OCR、表决盘和归档日志。实例层检查通不过时,别忘了ASM实例本身也可能出问题。ASM实例的检查入口是:

# 进入ASM实例 sqlplus / as sysasm # 查看磁盘组状态、可用空间、在线状态 SELECT group_number, name, type, state, total_mb, free_mb FROM v$asm_diskgroup;

STATE必须是MOUNTED或CONNECTED,如果某个磁盘组变成DISMOUNTED,数据库要访问该磁盘组上的文件就会直接报错。FREE_MB不足时,数据库可能出现 "ORA-01653 unable to extend table" 类错误,这时候很多DBA误以为是表空间不够,实际上可能是ASM磁盘组的可用空间已经告急。

v$asm_disk用来检查单块磁盘:

SELECT group_number, disk_number, name, path, mode_status, state, total_mb, free_mb FROM v$asm_disk WHERE group_number > 0 ORDER BY group_number, disk_number;

如果某个磁盘MODE_STATUS是OFFLINE,那就说明这块盘已经被ASM把数据重新镜像导出了,底层大概率是物理链路或者多路径软件的问题。配合crsctl status resource ora.DATA.dg看资源是否ONLINE,能快速判断是ASM层面主动弹出磁盘,还是磁盘确实下线。

4.3 监听故障排查实录:监听服务无法启动

项目标题下方的热词里出现了"oracle监听服务无法启动",这个太经典了。19c环境里监听无法启动,最常见的原因有两个:一是监听日志文件被撑满或损坏,二是listener.ora配置冲突,三是端口被占用。先说日志文件问题,10g之后监听日志默认路径是$ORACLE_HOME/network/log/listener.log,在某些场景下(比如大量连接尝试、反复连接失败)日志会变得非常大,出现TNS-12599: TNS:internal inconsistency error或者干脆启动失败。

我处理这类问题的标准路径:

  1. 停监听:lsnrctl stop LISTENER(停不下来就记录PID,手工kill,但要确保没有活动连接依赖这个监听)。
  2. 把现有listener.log改名,比如listener.log.bak_20260406。
  3. 确认端口没被占用:netstat -an | grep 1521或者lsof -i :1521。
  4. 启动监听:lsnrctl start LISTENER。
  5. 查看状态:lsnrctl status LISTENER,确认 "Services Summary" 里有对应的实例服务。

改日志文件这个操作,相当于让监听器新建一个空日志继续写,不删除历史数据还能保留证据,是"最简"做法里性价比很高的一个动作。另外注意,19c的监听还可能会出现私有IP和DHCP导致的TNS-01150问题,这时候要把listener.ora里的LISTENER的地址改成显式IP,别用主机名。

4.4 存储过程与性能排查的辅助手法

热词里还有"oracle存储过程""oracle ebs wip 非标工单"这类内容,说明很多读者日常跑的是EBS这类复杂系统,排查时会涉及存储过程和包的问题。RAC环境下,如果一个存储过程仅在特定节点报错,通常要去查gv$sqlarea里该存储过程中的SQL在各个节点的执行情况:

SELECT inst_id, sql_id, executions, elapsed_time / 1000000 AS elapsed_secs, cpu_time / 1000000 AS cpu_secs, buffer_gets, disk_reads FROM gv$sqlarea WHERE upper(sql_text) LIKE '%YOUR_PROCEDURE_NAME%' AND command_type IN (47, 48); -- 47是PL/SQL执行

如果同一SQL在节点1耗时明显比节点2高,优先怀疑该节点的性能基线,比如CPU配额、内存压力、或者某个节点的实例参数被误改。比如parallel_server_instances、service_names这类参数如果各节点不一致,就会造成执行计划在不同节点的表现完全不一样。这也是RAC和单机运维最大的差异点:参数必须以集群为单位保持一致,检查方法是用 spfile 加上sid='*'的设置,或者直接:

SELECT inst_id, name, value FROM gv$parameter WHERE name IN ('service_names', 'parallel_server_instances', 'memory_target');

只要两个节点的值不一致,就能解释很多"节点差异"问题。

5. 集群级深度排查实操

5.1 CRS组件状态逐项核对

集群层排查必须用crsctl,这条命令的产出信息量最大。19c里的核心资源包括ora.cssd、ora.diskmon、ora.evmd、ora.asm、ora.<db>.db、ora.<db>.<service>.svc、ora.<node>.vip、ora.<node>.ons、ora.scan*。检查整体状态:

crsctl status resource -t

输出的STATE列如果全部是ONLINE,集群健康;如果有OFFLINE、UNKNOWN、INTERMEDIATE,就要针对性看。比如监听资源ora.LISTENER.lsnr的状态是OFFLINE,那就是监听器的资源没有随集群启动,可以单独拉起:

crsctl start resource ora.LISTENER.lsnr

再比如DNS问题导致的ora.scan1.vip状态异常,先确认SCAN IP在网络里能被解析,再看crsctl status resource ora.scan1.vip是否ONLINE。

# 检查集群集群件服务进程是否正常 crsctl check crs

正常输出会显示:

CRS-4638: Oracle High Availability Services is online CRS-4537: Cluster Ready Services is online CRS-4529: Cluster Synchronization Services is online CRS-4533: Event Manager is online

如果Cluster Synchronization Services不在线,整个RAC就名存实亡了,节点间无法维持一致性,此时必须优先处理CSS(Oracle Cluster Synchronization Service)进程的问题。一般是看/var/log/messages和cssd.log里的网络、存储错误。

5.2 心跳与网络冗余排查

心跳(私有网络)是RAC的命脉。19c的集群通信依赖两个节点间的私有网卡,常用的是bond或者双网卡冗余。检查网络层面常用的命令:

# 查看集群节点互联信息 crsctl get node网络信息具有误导性,需要核对实际互联信息 # 查看私有网络IP(在19c中更好的是通过oifcfg) oifcfg getif

oifcfg getif输出里能看到每个网卡的接口名、子网、接口类型(public或cluster_interconnect)。正常情况下,至少有一对网卡被标记为cluster_interconnect,而且各节点的私有IP必须互通。实际操作中,我遇到过EMC网络隔离配置失误导致节点间心跳丢包,表现为数据库告警日志里一片 "IPC Send timeout" 和 Trace 文件疯狂增长,同时crsctl check cluster -all返回某个节点CRS-4537。这时候用ping测试私有IP,用ifconfig或ip a检查网卡错误包计数,基本能锁定问题。

另外,19c RAC的心跳默认会尝试使用UDP,如果确认网络存在延迟和丢包,需要检查$GRID_HOME/network/admin/sqlnet.ora里有没有配置SQLNET.OUTBOUND_CONNECT_TIMEOUT等与心跳无关的参数,不要随意调低misscount之类的隐藏参数。心跳问题最稳妥的处理是联系网络团队确认交换机端口、MTU、双工模式,而不是在数据库侧硬扛。

我个人的习惯是定期用简单脚本抓取各节点私有IP在通信时的延迟:

ping -c 100 -i 0.2 192.168.10.2 | tail -1

丢包率超过0,且伴随数据库日志里的CSS报错,就说明网络已经处于亚健康状态了。很多RAC节点驱逐事故,根源都在这里。

5.3 OCR、表决盘和日志文件状态检查

OCR和表决盘(Voting Disk)是集群的"记忆"和"选票"。OCR存集群配置,表决盘在节点间通信异常时表决谁能继续存活。19c里这些文件通常放在ASM磁盘组中。检查方式:

# 查看OCR配置与状态 ocrcheck # 查看表决盘配置与状态 crsctl query css votedisk

ocrcheck输出要看到 "Oracle Cluster Registry" 状态正常;crsctl query css votedisk输出应显示设备状态是ONLINE。如果表决盘有损坏,节点可能在通信异常时无法达成法定票数,导致两个节点都自杀(Split Brain),生产事故级别就大了。

日志文件的状态,重点看两个目录:数据库的trace目录和集群的log目录。当磁盘空间不足时,很多看似无关的故障(监听不能启动、ASM不能mount、资源状态异常)会成片出现,因为所有进程都在尝试写日志,写不进去就会挂。日常巡检时,对diag目录和集群日志目录的空间占用要格外敏感:

du -sh $ORACLE_BASE/diag/rdbms/*/*/trace du -sh $GI_HOME/log/<hostname>/*

如果发现某个节点alert_<sid>.log文件单日增长超过几百MB,要去看是不是有错误在循环刷屏,比如ORA-00600或者连接风暴产生的TNS-12541。这个动作在19c环境里比在11g里更值得做,因为19c的diag体系更完善了,日志增长带来的空间压力也更明显。

5.4 节点驱逐与重启的常见应对

节点被驱逐(Eviction)是RAC运维中最被动的场景,也是最需要冷静处理的事件。常见原因有三类:心跳中断触发misscount、ASM磁盘I/O大面积超时、文件系统hang导致进程无响应。当收到CRS-1002或ORA-29740报错时,不要急着把节点加回来,先找到驱逐的根因。

我处理过比较典型的案例是:存储路径切换导致所有节点同时出现ASM盘离线,其中一个节点先发起了重新挂载,另一个节点在等待I/O时超过CSS的misscount,被集群驱逐。在这类场景里,先确认存储链路是否恢复、ASM磁盘组状态是否正常,再手动启动被驱逐节点上的集群:

# 在故障排除后,重启被驱逐节点上的GI(需要root) crsctl stop crs crsctl start crs

启动后立即检查:

crsctl status resource -t

确认该节点的ora.<node>.vip、ora.<node>.ons、ora.<db>.db资源状态变成ONLINE。如果数据库资源起不来,再回数据库日志排查实例恢复过程。这里有一个经验:被驱逐节点的实例如果有大量在线重做日志恢复要处理,启动时间会比较长,但crsctl stat res -t看到的资源可能是INTERMEDIATE,不要误以为卡死,用tail -f $ORACLE_BASE/diag/rdbms/<db>/<sid>/trace/alert_<sid>.log观察Recovery Manager或SMON进度即可。

6. 常见问题速查表与排障实战记录

6.1 状态排查常见问题速查表

故障表象最可能的层第一排查命令备注
客户端报 ORA-12541/ORA-12514监听层lsnrctl status查看服务是否注册
实例状态 CLOSED,节点在线实例层crsctl stat res -t看数据库资源状态
节点A连接全部失败,节点B正常VIP/服务层crsctl status resource ora.<node>.vip看VIP是否在线
两个节点互相PING不通私有IP网络层ping私有IP查心跳丢包
OCR完整性失败集群元数据ocrcheck准备OCR恢复
磁盘组OFFLINE导致数据库报错ASM层v$asm_diskgroup看磁盘组状态
节点被驱逐后资源全OFFLINE集群层crsctl start crs必须root执行
归档停滞显示NO-ARCH归档层last_archive_time查归档目的地
存储过程只在一个节点慢性能层gv$sqlarea对比不同inst_id

这张表覆盖了我日常接到"RAC状态异常"工单时的第一反应。需要注意的是,表里每一行都只是"第一判断",真正的根因往往需要往下再追一层。比如lsnrctl status发现服务没有注册,后续可能还要查local_listener参数、listener.ora 的配置、ONS是否同步等。所以速查表的意义是"快速分层",不是"一步定位"。

6.2 我在生产环境中踩过的三个坑

第一个坑是分不清v$instance和gv$instance。刚接手RAC时,我曾经在节点1上执行select * from v$instance,看到节点1状态正常就回执"集群正常",结果节点2早就挂了。后来养成习惯:凡是RAC,一律用gv$前缀。19c的很多视图虽然自动做了聚合,但v$instance这种会话绑定的视图如果不带gv$,永远只能看到当前连接的节点。

第二个坑是crsctl status resource -t的输出被忽略的字段。资源状态表里有一列TARGET,一列STATE。不少DBA只看STATE是不是 ONLINE,忽略了TARGET。如果TARGET是 OFFLINE、STATE是 OFFLINE,那是"主动关闭";即使STATE显示 ONLINE,只要TARGET不是 ONLINE,集群重启后资源也会掉线。这个细节我在一次维保操作中吃过亏:手动把监听资源crsctl modify resource ... -attr "TARGET=OFFLINE"改掉了,忘记改回来,后来每次节点重启监听都不自动起,业务连着出了好几张工单。

第三个坑是 ASM 磁盘组空间判断只看了v$asm_diskgroup.free_mb,忽略了usable_file_mb。在普通冗余(normal redundancy)模式下,free_mb看起来很大,但usable_file_mb可能已经很小,因为ASM要把空间留给故障后的重新镜像。低于total_mb的20%就要警戒。19c的告警日内经常会出现ORA-15041(磁盘空间不足),提前用:

SELECT name, total_mb, free_mb, usable_file_mb FROM v$asm_diskgroup;

盯着usable_file_mb这一列,能规避很多扩容不及时引发的故障。

6.3 扩展:用Python定期巡检RAC状态的方案

最后给一个偷懒实用法的思路。热词里有 "python连接oracle查询数据",说明很多同行已经在用Python做运维自动化。cx_Oracle(现在改叫python-oracledb)连RAC集群执行状态巡检,完全没问题。我的简化版巡检脚本逻辑是:连接任意一个节点,执行gv$instance总览SQL,然后把结果按行打印或者写入一张状态历史表。

import oracledb conn = oracledb.connect(user="system", password="******", dsn="192.168.1.10:1521/ORCL") cur = conn.cursor() cur.execute(""" SELECT inst_id, instance_name, status, database_status, TO_CHAR(startup_time, 'YYYY-MM-DD HH24:MI:SS') FROM gv$instance ORDER BY inst_id """) for row in cur.fetchall(): print(row) cur.close() conn.close()

这个脚本再配合crontab每天定时跑,结果里如果出现非OPEN的状态就把它作为告警交给企业微信或邮件通知。这样做的价值不是替代专业监控软件,而是让"最简排查"变成"每日自动体检",很多隐患在变成故障之前就已经被看见了。

但有一点要提醒:巡检账号权限别给太高,能查视图和动态性能表就够了。RAC毕竟是多个节点协同工作的系统,任何一条巡检SQL都应当用gv$而不是v$,否则巡检数据本身就缺失了另一半节点,等于白做。

7. 个人经验与收尾建议

我在处理大量19c RAC状态排查之后,最深的一个体会是:多数"多节点异常"并不是数据库内核真的挂了,而是分层视角没有建立起来。我见过凌晨三点被电话叫醒,某位DBA在节点1上反复跑同样的SQL,却始终不去看节点2的实例是否还在线。跑通了这套"最简排查指南"里的动作,整个流程压缩到五分钟以内,问题90%都能定位到正确的层,剩下的10%也能把日志证据链拉完整再找原厂或社区求助。

最后再分享一个小习惯:每次正式变更或故障处理后,把gv$instance的快照、crsctl status resource -t的输出和所有相关日志压缩成一个以日期命名的文件,存到统一目录。下次再出状态问题,先拿这次的"健康基线"做对比,哪些字段变了、哪些资源状态漂移了,一眼就能看到。这个方法成本极低,但长期坚持下来,比任何监控面板都更适合快速判断"到底哪里不正常"。

19c RAC的排查本质上是一个熟练度游戏:命令就那么多,视图就那么多,关键是你知道在什么场景下先看哪一个。希望这份指南能帮你把"RAC状态排查"从一件容易紧张的事,变成一件按流程走、有把握的事。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询