简介:这是一份面向Oracle Database 11.2.0.3(Linux x86-64)环境的数据库补丁集更新包,对应补丁号20760997,包含2015年7月发布的CPU关键补丁更新。它主要服务于需要维护存量Oracle实例的DBA、系统运维与安全合规人员,用于补齐已知安全漏洞、修正稳定性与性能问题,并使数据库补丁基线保持一致。压缩包为zip格式,体积约100.73MB;上游未给出文件总数与类型明细,从描述看涉及补丁主体与检索说明类文件,具体构成以实际下载为准,适用场景需与Linux x86-64、11.2.0.3版本及依赖关系匹配。已有293人学习或下载,适合需要查阅补丁内容、做测试环境验证或安全加固的读者参考。其价值在于提供较完整的官方补丁集线索,便于围绕11.2.0.3.15基线开展漏洞排查、兼容性验证与变更前评估,对存量系统的维护和合规审计有实际帮助。
1. 两小时的等待,被一行 error 打回原形
凌晨两点,p20760997_112030_Linux-x86-64.zip解压到/u01/patch之后,opatch apply跑到 93% 停住,屏幕上只剩一句OPatch found the word "error" in the log files, please contact Oracle Support。同一套 oracle patch 流程,前面三台测试库都顺顺利利,偏偏这台要上线的 11.2.0.3 卡在这里。碰过p20760997这类补丁号的人大概都有同感:补丁包本身几乎不会坏,真正让人翻车的是 OPatch 版本、Inventory 注册、补丁冲突、SQL 层脚本这四道关卡,任何一道没对齐,报错都长成同一副面孔。这篇记录按我实际排错的顺序展开,从动手前的自检,到 apply 失败、SQL 层报错、回滚,每一段都给出能直接抄的命令和判断依据,适合正在给 11.2.0.3 打补丁、被 OPatch 拦下来的同学对照排查。
2. 动手前的三道门:OPatch 版本、Inventory 注册、环境变量
补丁包里那串名字不是随便起的,p20760997_112030_Linux-x86-64.zip拆开看就是「p + 补丁号 + 版本号 + 平台」:20760997是补丁编号,112030表示 11.2.0.3.0,后面是 Linux x86-64。版本号先对上,才谈得上后面的检查。很多人拿到包直接unzip然后opatch apply,跳过了下面三道门,结果在完全不同的地方收到同一句OPatch failed with error code 73。这章的三件事必须在停库之前做完,做完之后你对这套环境的现状才有底。
2.1 报错 “Patch is not applicable to this Oracle Home” 与 OPatch 版本错配
最典型的开场是这样的:补丁解压完,opatch apply秒退,日志里写着Patch is not applicable to this Oracle Home,或者干脆OPatch failed with error code 73。多数人第一反应是「补丁包下错了」,跑去重新下载一遍,结果一模一样。根因往往不在补丁,而在$ORACLE_HOME/OPatch这个目录太老。Oracle 的补丁对 OPatch 有最低版本要求,写在补丁自带的README.txt里,11.2.0.3 早期装的 OPatch 版本普遍偏低,遇到 2015 年之后发布的补丁就会被直接拒掉。
先别猜,把两边版本读出来对比:
# 以 oracle 用户执行,确认当前 OPatch 版本 $ORACLE_HOME/OPatch/opatch version # 解压补丁包,读补丁自带的版本要求,不要凭记忆 cd /u01/patch unzip -q p20760997_112030_Linux-x86-64.zip -d 20760997 grep -n -i "opatch" 20760997/README.txt | head -20opatch version输出的形如11.2.0.3.5,最后一段是 OPatch 自身的小版本号;README.txt里通常有一行OPatch Version: 11.2.0.3.12之类的最低要求。两个数字一比,低于要求就先升级 OPatch,再谈打补丁。升级动作本身也要留后悔药,别原地覆盖:
# 先备份旧 OPatch,出问题能整目录退回去 mv $ORACLE_HOME/OPatch $ORACLE_HOME/OPatch.bak.$(date +%Y%m%d) # 解压 OPatch 补丁到 ORACLE_HOME,注意解压目标是上层目录 cd /u01/soft unzip -q p6880880_112000_Linux-x86-64.zip -d $ORACLE_HOME # 属主必须还原,否则后续所有 opatch 命令都会报权限不足 chown -R oracle:oinstall $ORACLE_HOME/OPatch $ORACLE_HOME/OPatch/opatch version这里三个参数值得说明:-d $ORACLE_HOME表示把压缩包里的OPatch/目录释放到 ORACLE_HOME 下,所以不要写成-d $ORACLE_HOME/OPatch,否则会多出一层OPatch/OPatch;p6880880_112000是 OPatch 的通用补丁号,112000段代表适配 11.2 及以上版本;chown那行不能省,用 root 解压出来的目录属主是 root,oracle 用户跑opatch会直接失败。升级完成后重新opatch version确认,如果数字没变,检查PATH里是不是还挂着另一个旧的 OPatch。
还有一种情况:版本明明够了,仍然报Patch is not applicable。这时候要看$ORACLE_HOME指向哪个 home。机器上同时装了 DB home 和 Grid home 时,echo $ORACLE_HOME很容易在切换会话时指错,结果拿着数据库补丁往 Grid home 上打,OPatch 自然认为「不适用」。
2.2 “OPatchSession cannot load inventory” 的三种来源
第二道门是 Inventory。报错原文通常是OPatchSession cannot load inventory for the given Oracle Home,或者更直接一点Oracle Home is not registered in the Central Inventory。它的意思是 OPatch 找不到「这台机器上装了哪些 home、装过哪些补丁」的登记簿,没有登记簿就无法判断补丁能不能打、打完怎么回滚。
登记簿的位置由oraInst.loc决定,OPatch 的查找顺序是先看/etc/oraInst.loc,没有再看$ORACLE_HOME/oraInst.loc:
# 查看中央清单指针,两个路径至少有一个要存在 cat /etc/oraInst.loc 2>/dev/null || cat $ORACLE_HOME/oraInst.loc # 典型内容 # inventory_loc=/u01/app/oraInventory # inst_group=oinstall # 确认清单目录本身可读可写 ls -ld /u01/app/oraInventory ls -l /u01/app/oraInventory/ContentsXML/inventory.xml三种常见来源分别是:oraInst.loc被误删或内容被改(比如克隆环境时整机拷贝,路径还是源库的);清单目录属主不是oinstall组,oracle 用户读不了;inventory.xml里这个 home 的记录被手工编辑坏掉。第一种最好处理,按实际路径重建oraInst.loc即可;第二种chown -R oracle:oinstall /u01/app/oraInventory就能救回来;第三种要看inventory.xml,改之前务必先cp一份,这个文件坏了会让同一台机器上所有 home 都失去登记。
注意:如果
opatch lsinventory -detail列出来的 home 路径和$ORACLE_HOME不一致,说明你在用 A home 的 OPatch 查 B home 的清单,先export ORACLE_HOME=...再重试,别急着改清单文件。
2.3 打之前先存一份现场:lsinventory、lspatches 与 registry$history
我现在的习惯是,任何补丁动手前先落一份快照到一个独立目录,出问题时不用靠回忆。这不是流程洁癖,是被「打完补丁才想起来原来已经装过某个 one-off」坑出来的。
# 快照目录按日期命名,方便和后续对比 SNAP=/u01/patch/before_$(date +%Y%m%d_%H%M) mkdir -p $SNAP $ORACLE_HOME/OPatch/opatch lsinventory -detail > $SNAP/lsinventory.txt $ORACLE_HOME/OPatch/opatch lspatches > $SNAP/lspatches.txt sqlplus -S / as sysdba <<'EOF' > $SNAP/db_info.txt set pagesize 200 linesize 200 feedback off select name, open_mode, version from v$database, v$instance; select action_time, action, namespace, version, id from registry$history order by action_time; select count(*) invalid_cnt from dba_invalid_objects; EOFlsinventory -detail给的是二进制层装过哪些补丁,包括补丁号和安装时间;lspatches是精简版,一眼能扫完;registry$history是 SQL 层的补丁历史,由catbundle.sql写入,它记录的是「数据库内部真正执行过哪些 SQL 补丁」。这三份东西的价值在于对照:二进制层显示20760997已装、registry$history里却没有对应记录,那基本就是只打了 binary 没跑 SQL,后面第 4 章要讲的所有报错都从这儿来。
3. 预检查过不去:prereq、冲突、空间、权限四类拦截
OPatch 在真正改文件之前会跑一串 prereq 检查,任何一项没过就中止,日志落在$ORACLE_HOME/cfgtoollogs/opatch/下。这一层的好处是它拦得住,坏处是报错信息经常只有半句,剩下半句要自己去日志里捞。这章按发生频率从高到低排四类拦截,每类给出触发条件、根因和处置方式。把这几项过一遍,apply阶段的意外会少掉一大半。
3.1 CheckActiveFilesAndExecutables failed:还有进程挂着旧的可执行文件
报错长这样:
Prerequisite check "CheckActiveFilesAndExecutables" failed. The following active executables are not used by this Oracle Home: /u01/app/oracle/product/11.2.0/dbhome_1/bin/oracle意思是这个 home 下的bin/oracle还有进程在跑,补丁要替换这个文件,替换不了。根因很朴素:库没停干净。有人只关了数据库实例,忘了监听;有人关了实例,但 OEM agent、备份 agent、还有个把会话挂在共享内存上;RAC 环境更常见,只停了本节点实例,其他节点还在跑同一份二进制。
单独跑这项检查,确认到底哪些文件被占用:
# -ph 指向解压后的补丁目录,不是 zip 文件 $ORACLE_HOME/OPatch/opatch prereq CheckActiveFilesAndExecutables -ph /u01/patch/20760997-ph是 patch home 的缩写,指向解压出来的补丁目录。如果报错列表里出现了bin/oracle、bin/oracleO、lib/libclntsh.so之类,先停干净:
# RAC 环境走 srvctl,别手工 kill 实例 srvctl stop database -d orcl # 单机环境 sqlplus -S / as sysdba <<'EOF' shutdown immediate EOF lsnrctl stop # 最后确认一遍,输出应当只剩 grep 自身 ps -ef | grep -E "ora_|tnslsnr|oracle" | grep -v grepps那行是判定标准:除 grep 自身外不应有任何输出。如果清完进程仍然报同样的错,检查是不是有别的实例共用这个ORACLE_HOME——一个 home 挂多个库时,要全部停掉才能打二进制补丁,这一点在测试机上特别容易被忽略,因为测试库常年没人关。
注意:11.2.0.3 的补丁操作必须用 oracle 用户执行,只有
opatch auto这类需要动 CRS 的场景才由 root 发起。用 root 直接跑opatch apply会造成补丁目录属主错乱,后面回滚时更加麻烦。
3.2 Patch conflicts with / is a superset of:补丁冲突与超集判断
第二类报错在预检查阶段最常见:
Patch 20760997 conflicts with the patch 19769480或者:
Patch 20760997 is a superset of patch 19769480conflicts表示两个补丁都改了同一个文件,不能共存;superset表示你手上这个补丁已经包含了那个补丁的内容,再打就重复了。根因都是这台库上已经装过某个相关补丁,而你手上的包不知道这件事,或者知道了但不允许覆盖。
先让 OPatch 把冲突细节打全:
# 冲突检测要指向补丁目录,输出比默认 apply 详细得多 $ORACLE_HOME/OPatch/opatch prereq CheckConflictAgainstOHWithDetail -ph /u01/patch/20760997 # 同时确认这个冲突补丁是不是真的装过 $ORACLE_HOME/OPatch/opatch lspatches | grep -i 19769480处置有两条路,取决于冲突补丁的性质。如果它是可以摘掉的 one-off,先回滚再打新补丁:
# 回滚冲突补丁,注意 id 是补丁号 $ORACLE_HOME/OPatch/opatch rollback -id 19769480 # 回滚成功后再打目标补丁 $ORACLE_HOME/OPatch/opatch apply -silent如果冲突补丁是 PSU 这类不能单独摘的累积补丁,正确做法是申请一份 merge patch(合并补丁),把两者合成一个后再打。这时候强行-force是最坏的选择,OPatch 会跳过冲突检测把文件覆盖上去,短时间看不出问题,等到某条 SQL 走到被覆盖的那个模块,才会以ORA-00600内部错误的形式爆发,排查成本翻好几倍。
lspatches那行的用途是先证实冲突是否存在:有时候inventory里的记录和实际文件不一致,lspatches列不出这个补丁,说明清单漂了,就该先修清单而不是急着回滚。
3.3 CheckSystemSpace 与 /tmp 空间:补丁不是解压完就能装
第三类拦截不带感情色彩:Prerequisite check "CheckSystemSpace" failed。根因是 OPatch 在安装时要往$ORACLE_HOME/.patch_storage留一份补丁副本,用于后续回滚,同时apply过程会在/tmp下写临时文件。空间估算常被低估,因为补丁包是压缩的,解压后体积可能是压缩包的两到三倍,.patch_storage再存一份,实际占用又要翻倍。
# 单独跑空间检查,OPatch 会直接告诉你缺多少 $ORACLE_HOME/OPatch/opatch prereq CheckSystemSpace -ph /u01/patch/20760997 # 同时看两个位置的实际余量 df -h /tmp $ORACLE_HOME du -sh $ORACLE_HOME/.patch_storagedf -h要看的是挂载点余量而不是百分比,OPatch 要的是绝对空间。du -sh .patch_storage让你知道已经存了多少历史补丁副本——这个目录常年只增不减,跑过几年补丁的库轻松吃掉几十 G。清历史副本要谨慎:opatch rollback依赖这里的内容,删掉就失去回滚能力,我一般只清理明确不需要回滚的旧补丁目录,且清理前先确认lspatches里对应补丁已经不再需要退回。
/tmp空间不足还会以另一种形式出现:apply跑到一半报java.io.IOException: No space left on device。这时候 OPatch 的 JVM 已经写过临时文件,补丁可能处于半装状态,正确姿势是先看日志确认哪些步骤完成,再决定回滚还是重打,不能直接再跑一遍apply。
3.4 权限与用户:root 装过一次,后面全乱
第四类是隐性的,报错不一定在 prereq 里,而是以Permission denied、Unable to create directory、Cannot write to .patch_storage的形式散落在日志各处。根因只有一个:这个 home 之前被人用 root 操作过,OPatch目录或.patch_storage的属主变成了 root,oracle 用户后续所有写操作全部失败。
# 确认当前身份和关键目录属主 id ls -ld $ORACLE_HOME $ORACLE_HOME/OPatch $ORACLE_HOME/.patch_storage # 属主异常时统一修回来,注意这是运维操作,先确认没有其他用户依赖 chown -R oracle:oinstall $ORACLE_HOME/OPatch $ORACLE_HOME/.patch_storage chmod -R 775 $ORACLE_HOME/OPatchid那行确认自己是 oracle 还是 root,很多「玄学」问题其实就是会话里su过又忘了退出来。属主修复要在停库状态下做,避免修到一半有进程在写。这套操作做完再跑一次opatch lsinventory,能正常列出内容才说明权限通了。
4. 二进制装完了,数据库还在报错:SQL 层才是深水区
opatch apply显示成功,是所有环节里最容易让人放松警惕的一刻。补丁包里的二进制文件和 SQL 脚本是两件事:前者替换bin、lib下的可执行文件和库,后者要由 DBA 在数据库里手工执行,更新 SYS 下的包、视图、数据字典。11.2.0.3 上这步跑的是catbundle.sql,不是更高版本里的datapatch,别拿错工具。漏了这一步,库能起来,但一查就报错,而且报错信息和补丁八竿子打不着,非常折磨人。
4.1 ORA-06553 / ORA-04063:只打了 binary 没跑 catbundle
典型现象是补丁装完,应用连上来查询直接抛错:
ORA-06553: PLS-306: wrong number or types of arguments in call to 'X' ORA-04063: package body "SYS.DBMS_REGISTRY_SYS" has errors ORA-04063: view "SYS.DBA_REGISTRY" has errors根因很确定:bin下的二进制已经换成新版,数据库里的 PL/SQL 包还是旧版,两者接口对不上。更隐蔽的表现是连接正常、简单查询正常,只有走到某个特定功能才报错,因为只有那部分包受影响。这时候去查dba_registry_sqlpatch(高版本)或registry$history(11.2.0.3),会发现最近一条记录还停留在很久以前,根本没有本次补丁的痕迹。
补救动作是补跑 SQL 层脚本:
# 停应用连接,切到 rdbms/admin 目录执行 cd $ORACLE_HOME/rdbms/admin sqlplus -S / as sysdba <<'EOF' @catbundle.sql psu apply EOF@catbundle.sql是脚本入口,不能带路径之外的参数省略号;psu apply是动作标识,表示应用;回滚时对应写成psu rollback。这个脚本执行时间不短,中间会重建大量 SYS 对象,跑完要立刻检查结果:
sqlplus -S / as sysdba <<'EOF' -- 确认本次补丁已写入 SQL 层历史 select action_time, action, namespace, version, id from registry$history order by action_time desc; -- 统计无效对象,正常应当为 0 select count(*) invalid_cnt from dba_invalid_objects; -- 有无效对象就编译,跑完再统计一次 @?/rdbms/admin/utlrp.sql EOFregistry$history里出现本次补丁号,说明 SQL 层确实落库了;dba_invalid_objects计数不为 0 通常是编译没跑完或者中途失败,跑utlrp.sql重编一次,跑完还有残留就必须逐个看对象名,多半是某个包在编译时依赖了另一个还没编过的对象,反复跑utlrp.sql两到三次一般能收敛。
注意:RAC 环境二进制补丁要在所有节点打,但 SQL 层脚本只在一个节点跑一次,且必须在所有节点二进制都打完、实例全部重启之后跑,顺序颠倒会直接导致节点间版本不一致。
4.2 “OPatch found the word error in the log files” 到底该看哪里
这句是我最讨厌的报错,因为它什么都没说。apply结束时报这个,只代表 OPatch 在它自己收集的日志里扫到了error这个单词,可能是致命错误,也可能只是某个脚本打了句无关紧要的告警。真正的信息全在日志文件里。
# 日志目录按时间排序,取最新的一份 ls -lt $ORACLE_HOME/cfgtoollogs/opatch/ | head -5 # 在最新日志里捞真正的错误行,ORA- 开头的最可信 grep -n -i -E "ORA-|PLS-|failed|error code" $ORACLE_HOME/cfgtoollogs/opatch/opatch*.log | tail -40看日志有个顺序:先找ORA-和PLS-,这两类基本等于根因;再找error code,OPatch 自己的错误码比如 73、79、110 各自对应不同类别;最后才看failed,这个关键词噪音最大。tail -40是因为真正的失败点往往在日志末尾,前面大量输出是正常的拷贝进度。
如果日志里全是 SQL 脚本报的ORA-,说明二进制已经装上去了,问题出在 SQL 层,回到 4.1 处理即可;如果日志停在文件拷贝阶段,多半是空间或权限;如果是java.lang.OutOfMemoryError,那是 OPatch 的 JVM 堆不够,加大OPATCH_JAVA_OPTIONS后重跑。
4.3 回滚:opatch rollback 与 psu rollback 要成对做
补丁打坏了要退,opatch rollback只退二进制,SQL 层要单独退,这个不对称是很多人第二次翻车的地方。
# 第一步:停库,退二进制补丁 srvctl stop database -d orcl || true $ORACLE_HOME/OPatch/opatch rollback -id 20760997 # 第二步:启动到 mount 或 open,退 SQL 层 sqlplus -S / as sysdba <<'EOF' @?/rdbms/admin/catbundle.sql psu rollback EOF-id后面跟的是补丁号本身,不是文件名,也不是p20760997这种带前缀的写法。回滚依赖.patch_storage里保存的原始文件副本,所以这个目录一旦被清过,回滚就会报找不到备份文件,那时候只能走备份恢复。SQL 层的psu rollback会从registry$history找到上一次的记录做反向操作,顺序必须是先退二进制再退 SQL,反了会让脚本执行时二进制版本对不上。
回滚完成后同样要验证:opatch lspatches里不该再有20760997,registry$history最新一条应当是 rollback 记录,dba_invalid_objects计数回落。三项都对了才算退干净。
5. 常见问题与避坑:五处看着没事、实际会咬人的地方
这五条都来自真实踩坑,共同点是当时看起来一切正常,问题在几小时甚至几天后才浮现。每条按现象、原因、解决三段写,能对号入座就直接照做。
5.1 补丁显示成功,第二天应用开始零星报 ORA-00600
现象:opatch apply返回 success,lspatches能看到补丁号,当天业务正常,第二天开始偶发ORA-00600内部错误,错误参数指向某个内部函数。
原因:多半是冲突检测被绕过。之前有人为了赶时间用了-force,把与已有补丁冲突的文件强行覆盖,.patch_storage里的记录和实际文件已经不一致,运行时加载了半新半旧的模块。
解决:先用opatch lsinventory -detail和lspatches对照,确认当前实际生效的补丁组合,再决定是回滚到干净状态重新按顺序打,还是补一份 merge patch。-force这个参数我现在的态度是:除非厂商支持明确要求,否则一次都不该用。
# 确认是否有补丁处于「记录与实际不符」的状态 $ORACLE_HOME/OPatch/opatch lsinventory -detail | grep -A3 -i "patch description" $ORACLE_HOME/OPatch/opatch lspatches5.2 同一个 home 装了多个库,只停了一个就开打
现象:prereq 阶段报CheckActiveFilesAndExecutables失败,ps里明明看不到本库进程,但 OPatch 坚持说bin/oracle被占用。
原因:一个ORACLE_HOME下挂了两三个实例,包括常年没人管的测试库。停掉主库后其他实例还在跑,共享同一份二进制。
解决:ps -ef | grep ora_按实例名逐个确认,把该 home 下所有实例都停掉;如果是 RAC,srvctl status database看全节点状态,所有节点都要停。
# 列出该 home 下所有实例的进程,按 SID 分组确认 ps -ef | grep -E "ora_pmon_|ora_smon_" | grep -v grep5.3 补丁打完了,监听起不来
现象:数据库实例正常 open,lsnrctl start失败,或者起来之后客户端连不上,lsnrctl status显示服务未注册。
原因:补丁替换了bin/oracle和部分网络库,但监听进程是在打补丁之前启动的,仍然加载着已被替换的旧.so,路径指向的文件句柄已经变了。
解决:打完补丁必须完整重启监听,不能只reload。顺序是先停监听、再停库、打补丁、起库、起监听。
lsnrctl stop # 确认监听进程彻底退出 ps -ef | grep tnslsnr | grep -v grep lsnrctl start lsnrctl status5.4 环境变量指到了另一个 home,补丁打到隔壁去了
现象:opatch apply成功,lspatches也能查到,但连上目标库发现版本没变,某些功能还是旧行为。
原因:会话里的ORACLE_HOME是上一次操作遗留的值,实际打到了同机器上另一个 home。opatch version、lsinventory全都跟着这个错误变量走,看上去一切正常。
解决:每次动手前echo $ORACLE_HOME加which opatch双确认,两个路径必须属于同一个 home;执行apply时直接写全路径而不是依赖PATH。
echo "ORACLE_HOME=$ORACLE_HOME" which opatch ls -l $(which opatch)5.5/tmp被清空后,历史补丁记录对不上
现象:某次例行清理把/tmp下的文件删了,之后opatch lsinventory报清单读取异常,或者rollback找不到备份。
原因:OPatch 在安装过程中会把部分中间状态写在/tmp,某些版本还会在其中保留清单的临时副本,清理脚本无差别删除后,残留的锁文件和临时记录让后续操作判断错乱。
解决:确认没有opatch进程在跑之后,清掉.patch_storage下的锁文件再重试;日常清理脚本要把/tmp下与 OPatch 相关的目录排除。
# 确认无 opatch 进程后再处理锁 ps -ef | grep -i opatch | grep -v grep ls -l $ORACLE_HOME/.patch_storage/ | grep -i lock6. 快速定位:把两小时压成五分钟的排查顺序
被同一类报错折腾几轮之后,我固定了一套顺序,核心思路是「先分层,再定位,最后才动手」。层次只有四层:OPatch 自身、Inventory、二进制安装、SQL 层,任何报错先归到其中一层,再在该层里找证据,不要一上来就重装补丁。
第一步永远是读日志,不是猜。日志在$ORACLE_HOME/cfgtoollogs/opatch/下,按时间倒序取最新那份:
ls -lt $ORACLE_HOME/cfgtoollogs/opatch/ | head -3 LATEST=$(ls -t $ORACLE_HOME/cfgtoollogs/opatch/opatch*.log | head -1) grep -n -E "ORA-|PLS-|error code|Prerequisite check" "$LATEST" | tail -30第二步按报错关键词对号入座,下面这张表是我实际遇到频率最高的几类,左边是日志里的原文特征,右边直接给出该去的章节和首个动作:
| 日志特征 | 所属层 | 首个动作 |
|---|---|---|
error code 73/not applicable to this Oracle Home | OPatch 版本 | 比对opatch version与README.txt要求 |
cannot load inventory/not registered | Inventory | 检查/etc/oraInst.loc与清单目录属主 |
CheckActiveFilesAndExecutables | 二进制安装 | ps -ef确认该 home 下进程已清空 |
conflicts with/is a superset of | 二进制安装 | 跑CheckConflictAgainstOHWithDetail |
CheckSystemSpace/No space left | 二进制安装 | df -h /tmp $ORACLE_HOME |
ORA-06553/ORA-04063 | SQL 层 | 补跑catbundle.sql psu apply |
found the word "error" | 全部 | 打开日志 grepORA-找真错误 |
第三步是验证,不看验证结果的排错都是白干。二进制层用opatch lspatches | grep 20760997,SQL 层用registry$history最新记录,对象层用dba_invalid_objects计数,服务层用lsnrctl status加一次真实连接。四项都过,才算这次补丁真的落地,而不是「看起来成功了」。
# 一次性跑完四项验证 $ORACLE_HOME/OPatch/opatch lspatches | grep -i 20760997 sqlplus -S / as sysdba <<'EOF' select action_time, action, version from registry$history where rownum <= 3 order by action_time desc; select count(*) invalid_cnt from dba_invalid_objects; EOF lsnrctl status | grep -i "Service.*has"血泪经验浓缩成一句:OPatch 的报错信息永远只说结果不说原因,真正的原因 100% 在日志里,而日志里最值钱的行一定带ORA-、PLS-或Prerequisite check前缀。从那以后我每次动手前都强制走一遍「版本核对、清单确认、快照留存、停库验证」这四步,哪怕是在测试机上,也不再凭感觉直接apply——两小时的返工和五分钟的自检,选哪个其实不用想。希望帮到你。
本文还有配套的精品资源,点击获取