Oracle RU补丁回滚前必须确认是否已部分生效:若dba_registry_sqlpatch中存在status='SUCCESS'记录、dba_objects出现大量INVALID对象,或日志含ORA-00600[ktbdchk1]等错误,说明datapatch已执行或中断,此时opatch rollback无效,只能通过备份恢复或状态修复。

回滚前必须确认补丁是否已部分生效
Oracle RU补丁一旦执行opatch apply并触发datapatch,就不能简单用opatch rollback全量撤回。很多现场故障(比如你遇到的ASM磁盘组挂载异常)恰恰发生在“看起来回滚成功”之后——opatch rollback只清理$ORACLE_HOME/OPatch下的补丁文件和inventory注册项,但datapatch对数据字典的修改(如registry$sqlpatch表插入记录、PL/SQL包重编译、内部对象变更)不会被自动撤销。
判断是否已部分生效的关键信号:
-
SELECT patch_id, action, status FROM dba_registry_sqlpatch WHERE action = 'APPLY'—— 若有记录且status = 'SUCCESS',说明datapatch已跑完,此时opatch rollback无效 -
SELECT owner, object_name, object_type FROM dba_objects WHERE status = 'INVALID'—— 出现大量INVALID对象(尤其是DBMS_*或UTL_*包),大概率是datapatch中途失败导致字典不一致 - 日志里出现
ORA-00600 [ktbdchk1]或ORA-00704,基本可判定数据字典结构已被RU补丁修改,无法靠opatch工具还原
opatch rollback只能用于未运行datapatch的场景
如果你在opatch apply后、手动执行datapatch -verbose前就发现错误(比如Conflicts with installed patches或This patch is not applicable for this environment),这时opatch rollback是安全的。但必须满足三个前提:
- 数据库实例必须处于
MOUNT或SHUTDOWN状态,不能是OPEN;否则opatch rollback会报Database instance is running - 确认
datapatch确实没被执行过:检查$ORACLE_HOME/cfgtoollogs/sqlpatch/下无本次RU编号的日志目录(如35021191) - 回滚命令必须指定完整补丁ID:
opatch rollback -id 35021191,不能只写opatch rollback——后者会尝试回滚所有补丁,极易引发冲突
datapatch已执行后的“伪回滚”方案
一旦datapatch完成或中断,官方不提供标准回滚路径。实际能做的只有“状态修复”,而非真正回退:
- 若
datapatch卡在统计信息收集(常见于WRI$_OPTSTAT_HISTGRM_HISTORY等大表),可临时禁用该步骤:ALTER SYSTEM SET "_optim_dict_stats_at_db_cr_upg"=FALSE SCOPE=BOTH;,再重跑datapatch -verbose - 若出现大量
INVALID对象,不要直接@?/rdbms/admin/utlrp.sql——先查dba_errors定位具体编译错误,常见是PLS-00905: object <owner>.<object_name> does not exist</object_name></owner>,说明RU补丁依赖的底层对象未创建成功,需手动补全(如CREATE OR REPLACE PACKAGE DBMS_STATS) - 如果
registry$sqlpatch里已有RU记录但数据库无法启动,唯一可靠方式是用备份的ORACLE_HOME目录覆盖当前目录(这就是为什么滚动升级前必须tar -cvf gi_home_`hostname`.tar /oracle/app/19.3.0/grid)
RAC环境回滚必须按节点顺序逆向操作
RAC下补丁是滚动升级的,回滚也必须反向滚动——不能在节点1回滚的同时节点2还在运行新RU。否则会出现跨节点数据字典版本不一致,触发ORA-15081: failed to submit an I/O operation to a disk或ORA-01034: ORACLE not available。
正确顺序:
- 先停节点2的实例:
srvctl stop instance -d <db_name> -n <node2></node2></db_name> - 在节点2上执行
opatch rollback -id 35021191(若未跑datapatch)或恢复备份ORACLE_HOME - 启动节点2实例,确认
SELECT * FROM gv$instance中该节点版本已回落 - 再对节点1执行同样操作
- 最后在所有节点都启动后,统一运行
datapatch -verbose(此时它会检测到补丁已被移除,自动清理残留注册)
最容易被忽略的是GI Home的回滚——GI补丁必须先于DB补丁回滚,否则crsctl check crs会返回CRS-4638异常,整个集群心跳中断。而GI回滚失败时,ocrconfig -showbackup里最近的OCR备份时间点就是你最后的救命线。


















