opatch apply报“实例未关闭”是预检查硬拦截而非警告,因检测到pmon进程、共享内存段或监听服务仍在运行,shutdown immediate后残留资源(如CRS未同步、DG Broker自动拉起)亦会触发失败。

opatch apply 报“实例未关闭”是预检查失败,不是警告而是硬拦截
Oracle 的 opatch apply 在 11g 及以后版本(尤其是 19c)中默认启用严格预检查(prereq),只要检测到任何数据库实例处于 OPEN 或 MOUNTED 状态,就会直接中止执行,并输出类似 OPatch failed with error code 254 或明确提示 Database instance is still running。这不是可跳过的提示,而是设计上的安全闸门——它不关心你是否“只改几个 .so 文件”,只要实例进程存在,就拒绝写入补丁二进制。
哪些进程会被判定为“实例未关闭”
OPatch 检查的不是 SQL*Plus 连接,而是底层 OS 进程和共享内存段。以下任一存在都会触发失败:
-
ps -ef | grep pmon能看到ora_pmon_进程(即使数据库已 SHUTDOWN ABORT,pmon 可能残留) -
ipcs -m显示 Oracle 实例使用的共享内存段(key 关联$ORACLE_HOME)仍被占用 - 监听器(
tnslsnr)仍在运行,且其配置中包含该实例的服务名(部分补丁要求监听也停) - RAC 环境下,CRS 资源状态未清理:
crsctl stat res -t | grep ora.显示资源 ONLINE 或 INTERMEDIATE
为什么 shutdown immediate 后还报错?常见残留场景
看似执行了 SHUTDOWN IMMEDIATE,但实际仍有资源未释放:
- DBA 忘记切到对应
$ORACLE_SID环境,sqlplus / as sysdba连的是别的实例 - 使用
srvctl stop database -d停库后,没等 CRS 完全释放资源就跑opatch apply(尤其 RAC 节点2滚动升级时) - Windows 下服务未真正停止:
sc query OracleService显示 STATE = 4 RUNNING,需用net stop OracleService - Linux 上残留
oracle用户的后台进程(如ora_d000_*,ora_m000_*),需手动kill -9并确认ipcs -m清空
验证是否真关干净:三步快速确认法
别只信 SQL*Plus 输出,用这三行命令交叉验证:
-
ps -ef | grep -i "ora_[a-z][a-z]0*_—— 应无输出$ORACLE_SID" | grep -v grep -
ipcs -m | awk '$5 ~ /'$(basename $ORACLE_HOME)'/ {print}'—— 应无共享内存段关联当前 $ORACLE_HOME -
lsnrctl status | grep -i "service_name.*—— 若监听还在,应看不到该实例的服务条目$ORACLE_SID"
RAC 滚动升级时最容易忽略的是 CRS 资源状态同步延迟;Data Guard 备库打补丁前若未执行 ALTER SYSTEM SET dg_broker_start=FALSE,Broker 可能自动拉起实例,导致你以为关了,其实它又起来了。











