Oracle RAC 环境中 Public IP 连接失败故障分析报告


一、故障现象

某业务系统用户反馈,在尝试通过数据库节点的 Public IP 地址连接 Oracle RAC 实例时,出现以下错误:

$ sqlplus app_user/******@10.0.0.100:1521/orcl_service

ERROR:
ORA-12541: TNS:no listener

但使用同一节点的 VIP(Virtual IP)地址连接正常:

$ sqlplus app_user/******@10.0.0.101:1521/orcl_service
-- ✅ 连接成功

该问题仅影响 节点2(主机名:dbnode02) 的 Public IP 连接,节点1 正常。


二、背景知识:Oracle RAC 中的网络类型

在 Oracle Real Application Clusters (RAC) 架构中,每个节点通常配置三种网络接口:

网络类型 示例 IP 用途 是否推荐客户端连接
Public IP 10.0.0.100 用于 SSH 管理、应用直连(非最佳实践) ❌ 不推荐
VIP(Virtual IP) 10.0.0.101 高可用浮动 IP,节点故障时自动漂移 ✅ 推荐(若需指定实例)
Private IP 192.168.10.100 节点间心跳、Cache Fusion 通信 ❌ 禁止

📌 监听器行为说明
Oracle Grid Infrastructure (GI) 会自动管理监听器(Listener),并将其绑定到 VIP 和 Public IP(前提是集群服务正常运行)。如果集群资源异常,监听器可能只注册 VIP,导致 Public IP 无法访问。


三、故障诊断过程

步骤 1:确认错误含义

$ oerr ora 12541
12541, 00000, "TNS:no listener"
// *Cause: The connection request could not be completed because the listener
// is not running.
// *Action: Ensure that the listener is running on the remote system.

结论:目标 IP:1521 上无监听进程响应。


步骤 2:登录故障节点,检查监听器状态

grid 用户身份登录 dbnode02

$ su - grid
$ lsnrctl status

输出关键片段

Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.0.0.101)(PORT=1521)))

缺失 Public IP (10.0.0.100) 的监听地址!


步骤 3:确认操作系统网卡配置正常

$ ip addr show

输出示例:

2: eth0: <BROADCAST,MULTICAST,UP> ...
    inet 10.0.0.100/24 brd 10.0.0.255 scope global eth0      # Public IP
    inet 10.0.0.101/24 brd 10.0.0.255 scope global secondary eth0:1  # VIP

结论:Public IP 在操作系统层面已正确配置。


步骤 4:检查 Oracle Clusterware(CRS)整体状态

$ crsctl stat res -t

实际输出

CRS-4535: Cannot communicate with Cluster Ready Services
CRS-4000: Command Status failed

⚠️ 严重异常:Cluster Ready Services (CRS) 主进程无法通信!


步骤 5:检查底层 CRS 初始化资源

绕过主服务,直接查询初始化资源状态:

$ crsctl stat res -t -init

关键输出

--------------------------------------------------------------------------------
NAME           TARGET  STATE        SERVER       STATE_DETAILS
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.crsd       ONLINE  OFFLINE      dbnode02     Stopped

💡 ora.crsd 是什么?
它是 Cluster Ready Services Daemon,负责管理所有上层资源(监听器、数据库实例、VIP、ASM 等)。
若它处于 OFFLINE,则监听器虽在运行,但不会动态注册 Public IP,也无法响应集群配置变更。


步骤 6:定位 crsd.bin 启动失败原因

查看 CRS 日志:

$ cd $GRID_HOME/log/dbnode02/crsd/
$ tail -n 50 crsd.log | grep -i "error\|fail\|space"

发现关键错误

CLSU-00101: Operating System error message: No space left on device
ORA-09925: Unable to create audit trail file

⚠️ 注意:No space left on device 不一定表示磁盘空间不足,更常见的是 inode 耗尽


步骤 7:验证是否 inode 耗尽

$ df -h    # 检查磁盘空间
$ df -i    # 检查 inode 使用率

df -i 输出示例

Filesystem       Inodes   IUsed   IFree IUse% Mounted on
/dev/vg01/grid  1000000 999999      1   100% /u01/grid

确认:inode 使用率达 100%,导致无法创建新文件(包括审计日志、socket 文件等)。


步骤 8:查找占用 inode 的“罪魁祸首”

审计日志目录通常是重灾区:

# 查看审计目录文件数量
$ find /u01/grid/rdbms/audit -name "*.aud" | wc -l
987654

# 按大小排序(小文件多)
$ ls -l /u01/grid/rdbms/audit | head -5
-rw-r----- 1 grid oinstall 120 Jan 20 01:00 db_12345.aud
-rw-r----- 1 grid oinstall 118 Jan 20 01:01 db_12346.aud
...

💡 每个 .aud 文件平均仅 100~200 字节,但数量巨大,迅速耗尽 inode。


四、故障恢复操作

1. 清理审计日志(释放 inode)

# 删除 7 天前的审计文件(谨慎操作!)
$ find /u01/grid/rdbms/audit -name "*.aud" -mtime +7 -delete

# 验证 inode 释放
$ df -i
# IUse% 应显著下降(如从 100% → 60%)

2. 手动启动 CRS 资源

# 启动 crsd(使用 -init 模式)
$ crsctl start res ora.crsd -init

# 验证状态
$ crsctl stat res ora.crsrd -init
# STATE 应为 ONLINE

3. 验证监听器是否恢复 Public IP 监听

$ lsnrctl status

预期输出

Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.0.0.101)(PORT=1521)))  # VIP
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.0.0.100)(PORT=1521)))  # Public IP ✅

4. 测试连接

$ sqlplus app_user/******@10.0.0.100:1521/orcl_service
-- ✅ 应成功连接

五、根本原因分析

故障因果链如下:

审计日志未清理 
→ 生成海量小文件(.aud) 
→ 文件系统 inode 耗尽(IUse% = 100%) 
→ crsd.bin 无法创建新文件(如审计轨迹、socket) 
→ crsd.bin 进程崩溃并无法重启 
→ 监听器失去集群管理,不再注册 Public IP 
→ 客户端通过 Public IP 连接失败(ORA-12541)

🔑 根本原因运维未配置审计日志自动清理策略,导致底层文件系统资源(inode)耗尽,引发集群管理服务中断


六、优化与预防建议

1. 修改审计策略(推荐)

将审计日志写入数据库表,而非文件系统:

-- 登录数据库(sysdba)
SQL> ALTER SYSTEM SET audit_trail=DB SCOPE=SPFILE;
SQL> SHUTDOWN IMMEDIATE;
SQL> STARTUP;

优点:避免文件系统压力;可通过 SQL 查询审计记录;支持分区和归档。

2. 配置日志自动清理(若必须用文件)

创建 cron 任务定期清理:

# /etc/cron.daily/clean_audit.sh
#!/bin/bash
find /u01/grid/rdbms/audit -name "*.aud" -mtime +30 -delete
find /u01/app/oracle/admin/*/adump -name "*.aud" -mtime +30 -delete

3. 监控 inode 使用率

在监控系统(如 Zabbix、Prometheus)中增加指标:

# check_inodes.sh
THRESHOLD=85
INODE_USE=$(df -i | awk 'NR>1 { gsub(/%/,"",$5); if($6=="/u01") print $5 }')
if [ "$INODE_USE" -gt "$THRESHOLD" ]; then
  echo "CRITICAL: Inode usage ${INODE_USE}% on /u01"
  exit 1
fi

4. 客户端连接最佳实践

  • 禁止直接使用 Public IP 连接 RAC。
  • 推荐使用 SCAN IP(Single Client Access Name)实现负载均衡与故障转移。
  • 若需连接特定实例,使用 VIP

示例 tnsnames.ora

ORCL_SERVICE =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = scan-cluster)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = orcl_service)
    )
  )

5. 定期巡检 CRS 状态

加入日常运维脚本:

crsctl check cluster          # 检查集群健康
crsctl stat res -t            # 检查资源状态
df -i                         # 检查 inode

七、附录:常用诊断命令清单

目的 命令
查看 ORA 错误含义 oerr ora 12541
检查监听器状态 lsnrctl status
查看网卡 IP ip addr showifconfig -a
检查 CRS 状态 crsctl stat res -t
检查底层 CRS 资源 crsctl stat res -t -init
检查磁盘空间 df -h
检查 inode 使用 df -i
查找大数量小文件 find /path -type f | wc -l
清理旧审计日志 find /audit_path -name "*.aud" -mtime +7 -delete
启动 crsd crsctl start res ora.crsd -init