Oracle 19c RAC实例因IPC错误终止,主因是OS级IPC资源问题:RemoveIPC=yes导致登出即清空sem/shm、DefaultTasksMax过小引发fork失败(ORA-27300)、或异常终止后shm/sem残留致CRS失联。

Oracle 19c RAC 实例因 IPC 错误终止,基本不是数据库配置问题,而是操作系统级 IPC 资源被清理、占满或冲突——最常见诱因是 systemd 的 RemoveIPC=yes、DefaultTasksMax 过小、或信号量/共享内存残留。
为什么 RemoveIPC=yes 会导致实例突然终止
RHEL/CentOS 7+ 默认启用该行为:只要最后一个 oracle 或 grid 用户登出(哪怕只是退出一个 ssh 会话),systemd-logind 就会清空该用户创建的所有 IPC 资源,包括 ASM 和 DB 实例依赖的信号量集(sem)和共享内存段(shm)。结果就是正在运行的实例瞬间失去 IPC 设施,日志里立刻出现 semget failed: No space left on device 或 ORA-27300: OS system dependent operation: semget failed,随后 PMON 强制终止实例。
验证方式:grep RemoveIPC /etc/systemd/logind.conf;若输出为 RemoveIPC=yes,必须改掉。
修复步骤:
- 编辑
/etc/systemd/logind.conf,将RemoveIPC=yes改为RemoveIPC=no - 执行
systemctl restart systemd-logind(无需重启整机) - 注意:该设置需在所有 RAC 节点统一生效,否则一个节点清理、其他节点还在用,照样崩溃
DefaultTasksMax 过小引发 fork 失败(ORA-27300: fork failed with status 11)
从 SLES 12 SP2 和较新版本的 Oracle Linux 开始,systemd 通过 DefaultTasksMax 限制单个用户可创建的最大任务数(含进程、线程、内核线程)。默认值 512 远低于 Oracle RAC 实际需求(多实例 + 后台进程 + ASM + CRS,轻松超 4000)。一旦达到上限,fork() 系统调用直接返回 ENOMEM(status=11),表现为 ORA-27300、IPC0 或 DBW0 进程被杀,继而整个实例终止。
检查与修复:
- 查当前值:
systemctl show --property DefaultTasksMax - 编辑
/etc/systemd/system.conf,取消注释并设为:DefaultTasksMax=infinity - 执行
systemctl daemon-reload(部分系统需重启systemd,但推荐直接 reboot 确保生效) - 验证:重启后再次运行
systemctl show --property DefaultTasksMax,确认输出为infinity
IPC 资源残留导致启动失败或运行中卡死
异常终止(如 kill -9、主机宕机、CRS 强制 stop)后,Oracle 进程遗留的共享内存段(shm)和信号量(sem)不会自动释放。下次启动时,CRS 尝试复用相同 key,但发现资源已存在且状态异常,就会拒绝注册,表现为资源状态为 UNKNOWN,或实例启动卡在 STARTED 状态,alert 日志反复报 IPC send timeout、Cannot communicate with Cluster Ready Services。
安全清理流程(必须按顺序):
- 以 root 执行:
crsctl stop crs(确保无任何 CRS 进程) - 确认
ps -ef | grep pmon无输出 - 清理 shm:
ipcs -m | awk '$5 == "oracle" {print $2}' | xargs -I {} ipcrm -m {} - 清理 sem:
ipcs -s | awk '$5 == "oracle" {print $2}' | xargs -I {} ipcrm -s {} - 执行
ipcs -m -s,输出应为空;再运行crsctl start crs - 切勿跳过
crsctl stop crs直接清理,否则可能破坏 OCR 访问
容易被忽略的交叉影响点
单一 IPC 问题常触发连锁反应:比如 RemoveIPC=yes 清掉信号量后,ASM 实例无法响应,进而导致数据库实例报 ORA-15064;而 DefaultTasksMax 不足又会让 oraagent_grid 进程无法 fork 新子进程去检测监听器状态,最终表现为 srvctl status scan_listener 显示 UNKNOWN。所以排查时不能只盯一个错误码,要回溯时间线,看最早出现的 IPC 类日志(尤其是 oraagent_grid.log 和 alert.log 中的 semget、shmat、fork 相关关键词)。


















