简介面向 Oracle 11.2.0.1 数据库运维与实施人员的补丁安装文档适合需要完成单实例补丁升级、理解 OPatch 应用流程或排查补丁冲突的初中级 DBA 参考。整包仅含 1 个 doc 文件大小约 942KB以 Word 文档形式集中整理定位为可随查随用的实战维护手册便于在变更窗口前快速核对并摘录要点。已有 131 人学习说明其在同类补丁操作资料中具备一定参考价值。内容覆盖安装前实例状态确认与完整备份、OPatch 解压与环境变量配置、数字补丁从小到大依次应用、安装后版本核验以及 opatch lsinventory、rollback、prereq 等异常排查思路对补丁编号顺序与成功标志也有提示同时提醒留存补丁压缩包、重启后测试服务与更新维护记录可帮助读者建立清晰的补丁管理顺序降低升级风险并沉淀可复用的操作依据适合作为日常维护和交接参考。1. OPatch 显示 succeeded 之后服务没起来补丁失败为什么总在最后一步才暴露数据库打补丁这件事最容易让人放松警惕的就是最后一行输出OPatch succeeded。补丁号对得上提示确认时也敲了 y窗口一关重启服务器然后 OracleService 卡在“正在启动”或者干脆超时。真正折腾人的不是打补丁这个动作本身而是失败信号被推迟到重启之后才出现——前面漏掉的一个环境变量、一个没停干净的实例、一份没刷新的数据字典全都在这一刻集中还账。这套流程看着只有三步把解压出来的 OPatch 放到位、进补丁目录执行opatch apply、数字补丁按从小到大一个一个打。可每一步都有自己独立的报错OPatch failed with error code 73、Prerequisite check checkPatchConflicts failed、ORA-12560、ORA-01078看着都像“补丁打坏了”根因却分散在环境、顺序、服务状态三个层面。这篇写给正被opatch apply卡住、以及补丁打完后实例起不来的同学现象先摆清再一层层往下挖。2. opatch apply 秒退ORACLE_HOME、OPatch 版本、实例未停这三类前置报错opatch apply这条命令有个特点出错时它不会停下来等你刷几行字就退出cmd 窗口一关报错就没了。所以第一步永远不是去搜报错原文而是先把输出留住再回头逐行读。:: 把屏幕输出同时落到文件里事后才有得看 :: 先建好日志目录避免重定向到不存在的路径导致命令本身失败 mkdir D:\patch_log :: 21 表示把标准错误也并入标准输出OPatch 的关键报错大多走 stderr %ORACLE_HOME%\OPATCH\opatch apply D:\patch_log\apply_psu_01.log 21是覆盖写同一份补丁重打第二次时记得换个文件名别把第一次的现场覆盖掉。日志里真正有价值的是OPatch failed with error code N上面那二三十行那才是根因最后一行只是结论。这三类前置报错占了我在 11.2.0.1 上见过的绝大多数逐个拆。2.1 ORACLE_HOME 没设或指错层所有后续报错的源头最典型的现场是新开一个 cmd 窗口直接cd到补丁目录敲opatch apply得到ORACLE_HOME environment variable is not set或者OPatch could not determine the Oracle Home。原因很朴素——set设的变量只在当前窗口有效窗口一关就没了昨天设过不等于今天还在。还有一种是设了但指错层指到D:\oracle\product\11.2.0或者指到数据库名目录OPatch 找不到oraInst.loc和 inventory一样报错。:: 第一步永远是验证不是重设先看当前窗口里到底是什么 echo %ORACLE_HOME% :: 指向 dbhome_1 这一层Oracle Home 就是它不是它的上级 set ORACLE_HOMED:\oracle\product\11.2.0\dbhome_1 :: 顺手把 bin 和 OPatch 塞进 PATH后面 sqlplus、lsnrctl 都要用 set PATH%ORACLE_HOME%\bin;%ORACLE_HOME%\OPATCH;%PATH% :: 让 OPatch 自己认一遍 home能正常列出 inventory 才说明环境对 %ORACLE_HOME%\OPATCH\opatch lsinventory三个参数细节值得记一下。set ORACLE_HOME...后面千万不要跟分号set XD:\a;会把分号当成值的一部分OPatch 拼出来的路径就成了D:\a;\OPATCH。值也不要加引号set ORACLE_HOMED:\...会让引号进到变量里。路径里更不要有中文和空格这是下一节要展开的坑。判断环境是否真的生效看opatch lsinventory的输出头几行Oracle Home : D:\oracle\product\11.2.0\dbhome_1、Central Inventory : ...。这两行对不上后面所有命令都是在错误的前提下跑。Linux 上对应的是export ORACLE_HOME...同样只在当前 shell 有效用echo $ORACLE_HOME验证道理一模一样。2.2 OPatch 版本低于补丁要求requires OPatch version ... but current is ...11.2.0.1 这个版本自带的那份 OPatch 往往还停在 11.2.0.1.x 这一档而补丁包要求的 OPatch 版本通常更高。报错长这样Patch 1234567 requires OPatch version 11.2.0.3.x, but current is 11.2.0.1.x OPatch version 11.2.0.1.x is not supported这不是补丁包坏了是工具太旧读不懂新补丁的元数据。解决方式是把 OPatch 换掉而不是反复重下补丁。:: 1) 先整体改名备份别直接删新版跑不起来还能换回来 move %ORACLE_HOME%\OPatch %ORACLE_HOME%\OPatch_bak :: 2) 新版 OPatch 解压到 %ORACLE_HOME%\OPatch :: 注意层级解开后应当直接是 OPatch\opatch.bat 这一层 :: 很多压缩包解开是 OPatch\OPatch\opatch.bat多套了一层必须挪平 dir /b %ORACLE_HOME%\OPatch\opatch.bat :: 3) 验证版本号输出应当不低于补丁包要求的那个数字 %ORACLE_HOME%\OPATCH\opatch versionmove改的是目录名目录里原有的jlib、opatch.pl、opatch.bat一起搬走所以回退就是把两个目录名换回来。第 2 步的层级问题非常常见多套一层后opatch version报的是OPatch cannot find ...而不是版本号很容易误判成没装好。第 3 步的版本号要拿补丁包里的说明去对别凭记忆判断“应该够新”。还有一种相邻的失败OPatch 报Java could not be found或者直接一个 Java 异常栈。这通常是JAVA_HOME指到了一个不兼容的 JDKOPatch 自带的运行时又被环境变量盖住了。我一般先set JAVA_HOME清空再单独跑一次opatch version让 OPatch 用它自带的运行时能过就说明是新旧 JDK 打架。2.3 实例没停干净OPatch failed with error code 73前置检查里最硬的一条是文件和可执行体不能被占用。实例还在跑OPatch 会拒绝覆盖 dll 和可执行文件The Oracle instance is running. Please shut down the Oracle instance and all the services UtilSession failed: Prerequisite check CheckActiveFilesAndExecutables failed OPatch failed with error code 73先用 sqlplus 正常关不要上来就杀进程shutdown abort之后再startup一次能触发实例恢复但那是没有办法时的办法。-- 本地 sysdba 登录不需要密码Windows 上依赖当前用户属于 ora_dba 组 sqlplus / as sysdba -- immediate 会回滚未提交事务、写检查点比 abort 干净得多 shutdown immediate; -- 关完再确认一次这里报 ORA-01034 才是真的关掉了 select status from v$instance; exit:: 服务层面再确认光关实例不够监听和作业调度进程也要停 :: 服务名跟 SID 绑定OracleServiceORCL 里的 ORCL 换成你自己的实例名 sc query OracleServiceORCL net stop OracleServiceORCL net stop OracleTNSListener :: 看还有没有残留的 oracle 进程有就先记下 PID 再处理 tasklist | findstr /i oracleshutdown immediate卡住不动的情况也遇到过多半是某个大事务在回滚等的话可能很久。这时可以另开窗口shutdown abort然后startup让实例做一次恢复再shutdown immediate目的还是回到“干净关闭”这个状态。tasklist那一步是很多人漏掉的实例关了、服务停了但某个后台进程还攥着oracle.exe的句柄CheckActiveFilesAndExecutables照样失败重启服务器反而更快。同一台机器上有多个实例时这条尤其容易翻车只停了要打补丁的那个另一个实例共用同一个 Oracle Home 继续跑着error 73 一样会来。所以停服务之后sc query state all | findstr /i oracleservice把所有OracleService*列一遍更稳妥。2.4 路径带中文或空格、补丁目录套了两层does not contain any patch补丁包解压到D:\补丁\第一版\1234567这种路径OPatch 会在解析路径时抛出异常或者干脆说这个目录里没有补丁还有一种更隐蔽的压缩包解开后里面还有一层同名目录你停在外层OPatch 找不到etc、files这些该有的子目录同样报The patch location D:\patch\psu_01 does not contain any patch先用dir把目录内容看清楚比反复重下补丁有用得多。:: /d 才能跨盘符切目录只写 cd 在别的盘上是不生效的 cd /d D:\patch\psu_01 :: /b 只列名字看有没有 etc、files 这两个目录 dir /b :: 如果看到的是又一个同名目录再进去一层 cd /d D:\patch\psu_01\1234567 dir /b判断标准很简单目录里能看到etc、files以及一个记录补丁元数据的文件这一层就是opatch apply该执行的位置只看到一个同名文件夹就继续往里走。路径本身建议全部换成纯英文短路径比如D:\patch\psu_01、D:\patch\psu_02长度也尽量短——Windows 上路径过长加上补丁包里层级很深的文件会触发文件名超长失败报错往往莫名其妙跟补丁一点关系都没有。3. 补丁冲突与顺序checkPatchConflicts失败时先别急着重装数据库数字补丁要按从小到大的顺序一个一个打这条规则在很多文档里只是一句话没写为什么于是被当成玄学。等真的乱序打了看到Prerequisite check checkPatchConflicts failed第一反应往往是“补丁包有问题”接着就开始考虑重装数据库——这是最不该走的那条路。冲突报错的信息量很大只是藏在结论上面。3.1 为什么必须从小到大文件覆盖与前置依赖是两回事补丁包里装的是一批具体文件的新版本后一个补丁大概率也包含同一个文件。按顺序打等于让版本号一路往上叠乱序打后打的那个可能把文件换回更旧的版本OPatch 在CheckActiveFilesAndExecutables和冲突检查阶段就会拦下来。这是文件层面。另一层是 inventory 层面的前置依赖每个补丁在元数据里声明了自己依赖哪些前置补丁OPatch 会去中央清单里查这些前置补丁有没有登记过。你先把大的打了小的还没打依赖检查必然失败。所以顺序不是习惯问题是两道检查同时在卡。实操上还有个细节每个补丁都在自己的目录里执行set ORACLE_HOME这一步每个新窗口都要重来一次。一次打多个补丁时我习惯把每个补丁的日志按顺序编号存下来出了事能一眼看出是第几个开始不对。:: 每个补丁单独开一个窗口环境变量重设日志按序号命名 set ORACLE_HOMED:\oracle\product\11.2.0\dbhome_1 cd /d D:\patch\psu_01 %ORACLE_HOME%\OPATCH\opatch apply D:\patch_log\01_psu_01.log 21 :: 第一个确认 succeeded 之后再切到第二个补丁目录 cd /d D:\patch\psu_02 %ORACLE_HOME%\OPATCH\opatch apply D:\patch_log\02_psu_02.log 21cd /d是为了跨盘符切换set ORACLE_HOME放在最前面是因为每个新窗口都是白纸。判断能不能进下一个补丁唯一标准是日志里出现成功标记而不是“命令没报错就往下走”。中间弹确认提示时输入 y有些补丁会连问两次第二次不问就默认继续别以为卡住了。3.2 逐行读Prerequisite check checkPatchConflicts failed这个报错本身没有信息量值钱的内容在它上面。日志里通常有这么几种日志片段含义处理方向Missing prerequisite patch(es): [1234567]缺前置补丁inventory 里查不到先按顺序补打前置别跳过Patch 1234567 conflict with patch 7654321两个补丁改同一批文件且版本关系冲突确认先后关系必要时回滚后重打Patch is not applicable to this platform补丁包与当前系统或位数不匹配换对应平台的包不要强打This patch is already installed重复执行正常跳到下一个CheckActiveFilesAndExecutables failed文件被占用回到上一章停实例停服务Missing prerequisite是最常见的一条。它的意思不是“补丁包不全”而是“你以为已经打上的那个前置补丁在 inventory 里没有记录”。所以下一步不是继续找包而是先opatch lsinventory确认清单里到底有什么很可能前置补丁打是打了但当时 ORACLE_HOME 指到了另一个 home记录进了另一个清单。Patch is not applicable to this platform这条要特别注意它偶尔不是真的平台不对而是补丁目录层次不对OPatch 读不到元数据就退化成平台判断。先按 2.4 的dir /b确认目录层次再怀疑补丁包。3.3 顺序已经打乱回滚比重装快得多发现顺序错了正确动作是回滚后重来而不是硬着头皮往下打。回滚要按与安装相反的顺序后装的先退。:: 先拿到准确的补丁号和当前的清单状态别凭记忆 :: -detail 会把每个补丁的文件级信息都列出来输出较长建议重定向到文件 %ORACLE_HOME%\OPATCH\opatch lsinventory -detail D:\patch_log\inv_before_rollback.log 21 :: 回滚指定补丁id 从上面清单里抄不要手打 %ORACLE_HOME%\OPATCH\opatch rollback -id 1234567-id后面的数字必须和清单里完全一致抄错一位 OPatch 会报找不到补丁看起来像回滚功能不可用其实只是号码不对。回滚同样要求实例处于停止状态很多人栽在这里以为回滚是“撤销操作”所以不需要停机。有些版本的 OPatch 提供跳过冲突检查的开关我一般不用。跳过检查打进去文件版本关系是坏的当时能过业务跑一段时间才在某个功能上炸出来排查成本远高于现在回滚重打。3.4 建一份补丁台账lsinventory 与数据库侧的记录对得上补丁到底装没装、装到哪一版唯一可信的来源是清单不是记忆也不是某个目录里还剩几个压缩包。所以我打完一批补丁习惯把清单和数据库侧的记录都留一份。:: OPatch 侧的清单每个补丁的 ID、描述、安装时间 %ORACLE_HOME%\OPATCH\opatch lsinventory D:\patch_log\inv_after.log 21 :: 较新的 OPatch 提供 lspatches 子命令输出简表老版本只有 lsinventory -detail %ORACLE_HOME%\OPATCH\opatch lspatches-- 数据库侧能查到数据字典脚本的执行历史和 OPatch 清单互为印证 -- 只跑 opatch apply 没刷字典的话这里不会有新记录 select action_time, action, namespace, version, id, comments from registry$history order by action_time desc;这两份东西对不上就是 4.4 要讲的那类问题文件已经换了数据字典还是旧的。清单和registry$history的时间点应该能对上对不上就说明有一侧漏了。4. 补丁 succeeded 但实例起不来ORA-12560、ORA-01078 与漏跑的数据字典脚本补丁日志明确写了成功重启之后服务起不来或者连不上这类故障最容易被误判成“补丁把数据库打坏了”进而做出重装这种不可逆的决定。实际上它几乎都能拆成四层服务在不在、监听通不通、实例能不能挂载、数据字典对不对。从外往里查比一上来翻 alert log 快。4.1 先分层别一上来就翻数据文件第一步看服务状态第二步看监听第三步才连实例。顺序反了会在一个根本不存在的方向上空耗。:: 服务是否处于 RUNNINGSTOPPED 和 START_PENDING 是两种完全不同的故障 sc query OracleServiceORCL :: 监听在不在、注册的服务名对不对端口是不是 1521 lsnrctl status-- 服务正常的情况下本地 sysdba 应该能连上连不上说明实例根本没挂载 sqlplus / as sysdba select instance_status from v$instance;sc query输出里的STATE是关键START_PENDING卡住通常意味着实例启动过程中出错了这时候才需要看 alert log。alert log 在 11.2 里位于%ORACLE_BASE%\diag\rdbms\dbname\sid\trace\alert_sid.log补丁打完后的启动失败原因基本都写在里面而且时间戳清晰比猜快得多。4.2ORA-12560: TNS:protocol adapter error这个报错几乎只有一个含义客户端连不到本地实例。补丁本身不会改网络配置所以根因通常在服务或 SID 上。:: 当前窗口的 SID 是不是和你以为的一致这是最常见的差异 echo %ORACLE_SID% :: 设成实际实例名注意大小写习惯上和服务名保持一致 set ORACLE_SIDORCL :: 把机器上所有 Oracle 服务列一遍服务没起的话 SID 设对也没用 sc query state all | findstr /i oracleserviceset ORACLE_SID只在当前窗口有效这条和ORACLE_HOME是同一个坑只是症状不同。如果服务列表里压根没有OracleServiceORCL说明实例是用oradim注册的、注册信息丢了或者服务名不一样这时候纠结 SID 没意义得先确认实例对应的服务名到底是什么。还有一种情况是补丁打完、服务也起了但sqlplus / as sysdba报 ORA-12560而用完整连接串能连上。这说明实例是活的问题出在本地命名方式和认证方式上跟补丁无关按连接串那条路走就行别在补丁上继续找原因。4.3ORA-01078配LRM-00109spfile 找不到了这两个一起出现指向非常明确参数文件路径不对。ORA-01078: failure in processing system parameters LRM-00109: could not open parameter file D:\ORACLE\PRODUCT\11.2.0\DBHOME_1\DATABASE\INITORCL.ORALRM-00109会把它在找的完整路径打出来这个路径本身就是最有价值的线索。常见成因是 spfile 放在%ORACLE_HOME%\database下而补丁前后 Oracle Home 路径被动过或者当初建库时就用的 pfile、重启时 pfile 的位置变了。处理办法是用已知可用的 pfile 起来再重新生成 spfile。-- 用 alert log 里提到的、或者你手上确认存在的那份 pfile 启动 startup pfileD:\oracle\admin\orcl\pfile\init.ora; -- 起来之后确认参数确实加载了再重建 spfile show parameter spfile; -- 不带路径时会写到默认位置也就是 %ORACLE_HOME%\database 下 create spfile from pfileD:\oracle\admin\orcl\pfile\init.ora;startup pfile后面的路径必须真实存在写成相对路径容易因为当前目录不同而失败。show parameter spfile返回空值说明当前是用 pfile 起的还没用上 spfile。create spfile from pfile执行时实例必须处于启动状态这一点和很多人的直觉相反。重建完成后正常shutdown再startup确认不再报ORA-01078这一层就算过去了。4.4 补丁打了但字典没刷catbundle.sql漏跑这是最容易被忽略的一步也是“OPatch 明明 succeeded功能却不对”的典型根因。opatch apply换的是二进制和一部分脚本文件数据库内部的数据字典还需要单独刷一次否则版本记录、部分视图、部分包的状态都还是旧的。11.2 上对应的动作是跑 catbundle。-- 用 sysdba 登录后执行? 代表 ORACLE_HOME是 sqlplus 的内置替换符 -- cpu apply 对应 CPU 补丁psu apply 对应 PSU 补丁按你实际打的类型来 ?/rdbms/admin/catbundle.sql psu apply这条脚本跑的时间不短中间会刷出大量输出脚本本身会在当前目录生成日志文件。判断成功不看刷屏内容跑完之后再查一次registry$history最新一条记录的时间和补丁号应该能和你刚打的补丁对上同时对一下opatch lsinventory里的时间两边一致才算闭环。补丁包里的说明有时候要求先把数据库起在升级模式再跑脚本有时候直接在 open 状态跑。这两种要求我都见过具体按包里的说明走不要凭经验硬套。跑之前做一次完整备份这条不用强调也应该成为肌肉记忆——catbundle 出问题不像改错一个参数那么好回退。5. 避坑清单打补丁前后最容易翻车的 5 个瞬间这几个坑的共同点是命令都没报错看起来一切正常问题在几小时甚至几天后才出现那时候现场早就没了。按“现象 → 原因 → 解决”记一遍比读十页手册管用。5.1 清单里明明有补丁换台机器就查不到现象同一台服务器在 A 窗口opatch lsinventory能看到刚打的补丁在 B 窗口或者远程登录后却显示没有补丁。原因九成是ORACLE_HOME指到了另一个 home或者oraInst.loc指向的中央清单不是同一个——机器上装了两套 Oracle 产品时特别容易发生。解决是先确认输出头部的Oracle Home和Central Inventory两行再动手两个窗口的这两行必须完全一致。我一般把这两行连同lsinventory完整输出一起存进日志文件出问题时对着比比反复敲命令快。5.2 补丁打到一半窗口被关补丁处于半装状态现象opatch apply跑到一半cmd 窗口被误关或者机器重启再进来重打报Patch is already installed或者文件级校验失败。原因是 OPatch 已经写了一部分文件、也在清单里登记了但没走完收尾流程。解决是先opatch lsinventory -detail看这个补丁记录是否完整不完整就opatch rollback -id回滚干净再重打回滚也失败的话把OPatch\logs里对应时间的日志留着那里面记录了它到底停在哪一步。补丁执行期间不碰窗口、不断电这条比任何善后手段都有效。5.3 补丁包平台或位数不匹配硬打进去现象opatch apply报Patch is not applicable to this platform或者在文件覆盖阶段报一堆 dll 相关的错误。原因是从别的环境拿来的补丁包位数或者操作系统对不上。有人会去找跳过检查的开关强行推进这一步风险极高——文件版本关系和二进制不匹配数据库可能起来但在某个功能点上崩且崩的时候没有任何提示指向补丁。解决办法只有一个换对应平台的包。补丁包文件名里通常带平台标识下载时多看一眼比事后回滚省事。5.4 只备份了数据文件没备份 Oracle Home现象补丁冲突需要整体回退发现只能回滚 OPatch 层面而 Oracle Home 里的二进制已经变了回滚脚本又不完整。原因是备份策略只覆盖了数据文件、控制文件、参数文件没有覆盖 Oracle Home——毕竟它看起来“不会变”。实际上补丁改的正是它。常见的做法是在打补丁之前把整个 Oracle Home 目录复制一份到别的盘占空间但那是在补丁全线失败时唯一能快速恢复的东西。这份东西我把它当成后悔药希望永远用不上。5.5 补丁打完了没重启直接开始业务验证现象补丁日志成功lsinventory也对但某些功能行为还是旧的。原因是部分文件在服务运行期间被加载进内存没有重启服务或服务器就不会重新加载。项目里的做法很明确补丁全部打完之后重启服务器让 Oracle 服务随之自动启动再做验证。不重启就开始验证得到的结论不可信还会把“没生效”误判成“补丁有问题”白折腾一轮。6. 十分钟定位三条固定动作把报错范围缩到一层补丁相关的报错看着五花八门实际上每次都落在四个层里的某一层环境层ORACLE_HOME、OPatch 版本、路径、状态层实例和服务停没停、顺序层前置补丁和冲突、数据层数据字典刷没刷。十分钟定位的意义不是立刻修好而是先把范围缩到一层避免在四个层之间来回跳。我固定走三个动作。第一个动作是翻日志的开头部分不看最后一行。opatch apply的日志里OPatch failed with error code只是结论前面二三十行才是原因尤其是Prerequisite check那几行。第二个动作是跑一次opatch lsinventory只盯输出头部的Oracle Home和Central Inventory这两行不对后面所有判断都没有意义。第三个动作是在数据库侧查registry$history和清单的时间点对一下看文件和数据字典是不是同步的。报错或现象第一眼看哪里常见原因ORACLE_HOME environment variable is not set当前窗口echo %ORACLE_HOME%新开窗口没重设或指到了上一级目录OPatch failed with error code 73实例状态、Oracle 相关服务、残留进程实例没关净或多实例共用同一个 Homerequires OPatch versionopatch version输出OPatch 太旧需要整体替换does not contain any patch补丁目录dir /b路径含中文空格或目录多套了一层checkPatchConflicts failed报错上面二三十行乱序、缺前置补丁、重复打ORA-12560echo %ORACLE_SID%与服务列表SID 不一致或服务未启动ORA-01078配LRM-00109alert log 里打出的参数文件路径spfile 丢失或路径变更清单有记录但功能异常registry$history最新一条catbundle 没跑字典没刷新这张表是我自己出事时对着看的那一份不需要背出问题时按现象找到一行就知道该往哪一层挖。真正要养成的习惯只有一个每次opatch apply都重定向日志、每次打完都存一份lsinventory、每次验证都查一次registry$history。血泪经验是我曾经在一个补丁上折腾了大半天最后发现只是新开的窗口里忘了set ORACLE_HOME而前面所有排查都建立在“环境是对的”这个错误前提上。从那以后我每次动手前都强制先跑一遍echo %ORACLE_HOME%和opatch lsinventory | findstr /i Oracle Home三十秒的事能省掉半天。希望帮到你。本文还有配套的精品资源点击获取