简介:面向 Oracle 11.2.0.1 数据库运维与 DBA 学习者的补丁安装操作文档,围绕实例停机、完整备份、补丁包解压、OPatch 环境配置、逐个应用数字补丁及安装后验证等环节,梳理从准备到收尾的完整流程,并补充补丁查看、回滚与前置条件检查等排错思路,适合需要按步骤完成补丁升级或复盘操作要点的技术人员参考。资源包共 1 个 doc 文件,约 942KB,以图文/文字步骤说明承载操作命令与注意事项,体积轻便,便于离线查阅和按章节对照执行。已有 131 人学习,说明其在同类数据库维护资料中具备一定参考价值。读者可据此了解 set ORACLE_HOME、opatch apply、lsinventory 等关键命令的使用场景,掌握数字补丁由小到大的安装顺序、成功标志判断、服务重启及功能测试要点,减少因环境变量或补丁顺序不当导致的反复排查。
1. 补丁不是装上就完事:11.2.0.1 这套老库真正在补什么
一台还在跑老业务系统的 Oracle 11.2.0.1,安全扫描报了几个组件漏洞,运维把补丁包扔过来,要求"周末窗口打一下"。很多人以为这事就是三条命令:设ORACLE_HOME、进补丁目录、opatch apply。真到现场才发现,oracle11.2.0.1数据库打补丁这件事的成败几乎不在那三条命令上,而在前面二十分钟的准备和后面十分钟的验证——OPatch 版本对不对、库停干净没有、冷备能不能还原、补丁顺序有没有乱、打完数据字典编译没有。这份 doc 就是一份按顺序执行的操作记录,把解压位置、停库、逐个 apply、重启验证串成一条线,适合手上有一台不能随便重建的 11.2.0.1、需要一个字一个字照着敲完的从业者。
2. OPatch 先行:工具版本不对,补丁包连门都进不去
OPatch 是 Oracle 自带的补丁管理器,本质是个 Java 程序,负责把补丁里的文件拷进ORACLE_HOME、改注册信息、维护一份 inventory。补丁包本身只是一堆文件加一个etc/config.xml描述,能不能装进去、装进去登记得对不对,全看 OPatch 认不认这个格式。
这就引出一个很现实的问题:11.2.0.1 是这套大版本的基础版,随安装介质附带的 OPatch 往往是很早的版本,而后期的补丁包会明确要求"最低 OPatch 版本不得低于某个值"。不换工具直接 apply,最常见的报错是版本不兼容,连补丁内容都还没开始校验就退出了。所以顺序必须是先升级 OPatch,再谈打补丁。
2.1 先摸清现状:lsinventory 和 version 两条命令
动手之前先在命令行窗口里把现状记下来,这既是给自己留底,也是后面判断"到底成没成"的基线。
rem 第一步:把 ORACLE_HOME 指到目标库的 home,注意是 dbhome 不是基目录 set ORACLE_HOME=D:\oracle\product\11.2.0\dbhome_1 rem 查看 OPatch 自身版本 %ORACLE_HOME%\OPATCH\opatch version rem 查看这个 home 上已经打过的补丁清单 %ORACLE_HOME%\OPATCH\opatch lsinventoryopatch version输出的那一行版本号要和补丁包 README 里写的最低要求对一下,低了就先换 OPatch,别抱侥幸。lsinventory的输出比想象中重要得多,它会列出当前 home 的路径、已安装组件和已有的补丁号,如果目标补丁号已经在列表里,说明这台机器之前打过,重复 apply 会直接报"already installed"。
我一般会把lsinventory的完整输出重定向到一个文本文件存起来:
%ORACLE_HOME%\OPATCH\opatch lsinventory > D:\patch\lsinventory_before.txt 2>&1出问题时这份"打补丁前"的快照就是唯一的对照物,比事后回忆靠谱。
2.2 解压位置:OPatch 覆盖 home,补丁包单独放
原文里那句"解压的放 OPatch 其他的在补丁目录执行命令就好",说的其实是两件事,很多人第一次做会混。
OPatch 升级包解开以后是一个OPatch目录,要把它覆盖到%ORACLE_HOME%下面,也就是最终路径变成D:\oracle\product\11.2.0\dbhome_1\OPatch。覆盖前先把老的目录改个名,留一条退路:
rem 进入 ORACLE_HOME 所在层级 cd /d D:\oracle\product\11.2.0\dbhome_1 rem 老工具备份,出问题能立刻换回来 move OPatch OPatch_bak_20240101 rem 把新 OPatch 解压到当前目录,解压后应存在 .\OPatch\opatch.bat rem 这里用 Windows 自带解压或第三方工具均可,关键是层级要对数字补丁包则完全相反,不要解压到 home 里,找一个独立目录存放,比如D:\patch\,每个补丁一个子目录。原因是opatch apply的工作目录必须是补丁包自身的根目录——也就是那个含etc、files子目录的层级。在父目录里执行会得到一句非常经典的报错:
OPatch failed with error code 73 ERROR: The patch location "D:\patch" is not a valid patch area.这句话跟补丁损坏、跟权限、跟版本全都没关系,就是站错地方了。踩过一次之后我养成习惯:解压完先dir看一眼当前目录有没有etc\config.xml,有才继续。
2.3 多个 home 并存时的处理边界
一台服务器上装了两个 home(比如一个跑生产库、一个跑测试库),或者 RAC 环境下多个节点,OPatch 是跟着 home 走的,必须每个 home 各做一遍,不能只做一个然后指望另一份自动同步。
这里有个容易被忽略的边界:ORACLE_HOME这个环境变量是窗口级的。你在这个 cmd 窗口里set了,新开一个窗口就是空的。所以跨 home 操作时,千万别在一个窗口里连续set两次然后跑两遍 apply,很容易第二次没生效而你以为生效了。稳妥做法是一个 home 一个独立窗口,或者干脆在批处理里用setlocal隔离。
另外,如果机器上装了别的 JDK 并写进了系统JAVA_HOME,OPatch 有可能去用那个 JDK 而不是 home 自带的,报出各种类找不到的错误。遇到这种情况临时清掉再执行:
rem 只在当前窗口生效,不影响系统配置 set JAVA_HOME= %ORACLE_HOME%\OPATCH\opatch version3. 停库与冷备:那 20 分钟决定后面要不要回滚
补丁 apply 的过程会替换ORACLE_HOME下的二进制文件和库文件,如果此时实例还在跑,操作系统的文件锁会让替换失败,更糟的情况是替换了一半、进程还在用旧的内存映像,最后库处于一个说不清的状态。所以停库不是走流程,是硬性前置条件。
而备份这件事,我见过太多人嘴上说"备了",实际只备了数据文件没备参数文件,真出事的时候spfile里的参数对不上,恢复照样卡住。
3.1 关实例、停服务、清残留进程
标准动作分三层:先关数据库实例,再停 Windows 服务,最后确认没有残留的 oracle 进程。
-- 以管理员身份登录,不走监听,避免监听层干扰 sqlplus / as sysdba -- 关闭前先看一眼状态,确认没有异常会话在跑长事务 select instance_name, status from v$instance; -- 正常关闭,等待所有会话退出 shutdown immediate; -- 如果 immediate 卡住超过几分钟,说明有大事务回滚,不要强杀shutdown immediate之后实例是没了,但 Windows 服务OracleService<SID>可能还在,监听服务OracleOraDb11g_home1TNSListener通常可以留着不开机自启。停服务用:
rem 先查服务实际名称,不同安装方式命名会略有差异 sc query state= all | findstr /i "OracleService" rem 按查到的名字停,SID 换成实际值 net stop OracleServiceORCL停完必须验证,不能凭感觉:
rem 检查是否还有 oracle 相关进程驻留 tasklist | findstr /i "oracle" rem 检查关键文件是否还被占用,被占用会提示无法删除有残留就说明某个后台进程没退干净,这时候硬上 apply,十有八九在替换oracle.exe时报"文件正被另一进程使用"。
3.2 冷备清单:别只备数据文件
冷备的价值在于"整份拷走、整份放回",所以要覆盖的东西比想象中多。下面这张表是我实际会逐项打勾的:
| 类别 | 具体内容 | 备注 |
|---|---|---|
| 数据文件 | .dbf全部 | 含 system、sysaux、undo、用户表空间 |
| 控制文件 | control01.ctl等多路 | 多路复用时要全备 |
| 联机日志 | redo01.log等 | 冷备状态下可拷 |
| 参数文件 | spfile<SID>.ora或init<SID>.ora | 在%ORACLE_HOME%\database下 |
| 密码文件 | orapw<SID> | 同名目录 |
| 网络配置 | listener.ora、tnsnames.ora | 在%ORACLE_HOME%\network\admin |
| 归档日志 | 若库为归档模式 | 尽量保证备份点后能前滚 |
备份命令本身很朴素,关键是最后要校验:
rem 用 robocopy 整目录镜像,比 xcopy 稳,会返回明确的退出码 robocopy D:\oracle\oradata\ORCL E:\backup\before_patch\oradata /MIR /R:1 /W:1 rem 参数文件与控制文件单独再拷一份 robocopy D:\oracle\product\11.2.0\dbhome_1\database E:\backup\before_patch\database /MIR rem 校验:对比源和目标的文件数量与总字节数 dir D:\oracle\oradata\ORCL /s | findstr "个文件" dir E:\backup\before_patch\oradata /s | findstr "个文件"/MIR是镜像模式,会删除目标端多余文件,第一次用要确认目标目录是空的或者是专用备份目录,别指到一个有其它东西的盘上。/R:1 /W:1把重试次数压到最低,避免某个文件被占用时无限重试卡住批处理。
3.3 备份没做成就别开打
有个判断标准值得说清楚:如果备份过程中出现任何"跳过""部分失败",先解决它,不要带着残缺的备份往下走。补丁本身回滚是有手段的(opatch rollback),但回滚只回退ORACLE_HOME里的文件,回退不了数据。一旦补丁引发数据字典层面的一致性问题,能救你的只有冷备。
反过来,如果备份完整、校验通过,那心里就有底了——最坏情况无非是把整个目录拷回去、把服务起起来,代价是停机时间拉长,但业务能恢复。这个底气值那二十分钟。
4. 逐个 apply:数字包从小到大的执行顺序与输出判读
准备工作做完,进入正题。原文里说得很直白:一个补丁一个补丁地打,分别进各自的目录,执行设变量和 apply 两条命令,看到 succeed 就算过。这套流程本身没问题,问题在于"看到 succeed"这个判据太弱,以及顺序为什么必须从小到大没说透。
4.1 环境变量与当前目录的作用域
单个补丁的完整动作就是两条命令,但两条命令之间有严格的先后和位置要求:
rem ① 设置 ORACLE_HOME,指向目标 home set ORACLE_HOME=D:\oracle\product\11.2.0\dbhome_1 rem ② 切换到补丁包自己的根目录,注意是含 etc 子目录的那一层 cd /d D:\patch\11111111 rem ③ 调用 home 里的 opatch 执行安装 %ORACLE_HOME%\OPATCH\opatch apply参数说明:apply后面不加路径时,OPatch 默认取当前目录作为补丁位置,这也是为什么第 ② 步不能省。如果想显式指定,可以写opatch apply -ph D:\patch\11111111,但多数人还是习惯靠cd,因为后续看日志时目录对得上更直观。
apply执行过程中会交互式问一句"是否继续",自动化场景加-silent可以跳过;但第一次打某个补丁时我建议不加,让它把校验信息打全,出了问题好定位。
4.2 输出里除了 succeed 还该看什么
一段成功的 apply 输出里,真正值得盯的是这几处:
| 输出片段 | 含义 | 要不要管 |
|---|---|---|
Oracle Home | 确认打到了哪个 home | 必须核对,打错 home 是重大事故 |
Verifying the update... | 补丁与 home 的兼容性校验 | 有 WARNING 要逐条看 |
Patch <号> successfully applied | 单个补丁落地 | 正常 |
Composite patch <号> successfully applied | 复合补丁落地 | 正常 |
OPatch succeeded. | 整体成功 | 最终判据 |
Log file location | 日志路径 | 失败时第一时间去看 |
Oracle Home那一行是我每次必看的,尤其在多 home 机器上。有次在一个双 home 环境里,第一个窗口设ORACLE_HOME到 A,第二个窗口忘了设,继承了系统的环境变量指到 B,结果补丁打进了测试库的 home,生产库这边一直显示"没打上",排查了快一个小时才发现是环境变量的事。
失败时不要只看最后一行,OPatch 的日志里会记录具体是哪个文件的哪个检查没过,路径通常在%ORACLE_HOME%\cfgtoollogs\opatch\下,按时间戳找最新的那份。
4.3 多个补丁的顺序:为什么必须从小到大
补丁号是递增分配的,越大的号越新。之所以要按从小到大打,是因为后出的补丁往往是在前面的基础上累积的,它可能覆盖前一个补丁改过的同一个文件。反过来先打大的再打小的,小的会把大的改过的内容覆盖回去,最终 inventory 里登记了两个补丁,但实际生效的是旧的那份,这种"看起来都装上了、实际只有一半生效"的状态最难查。
原文说"一个一个打",是因为 11.2 时代的 OPatch 一次只能处理一个补丁目录,不支持把多个目录塞给一条命令。补丁数量多的时候手敲容易漏,写个批处理更稳:
@echo off setlocal enabledelayedexpansion set ORACLE_HOME=D:\oracle\product\11.2.0\dbhome_1 set OPATCH=%ORACLE_HOME%\OPATCH\opatch.bat rem 补丁号按从小到大排列,顺序不能改 for %%P in (11111111 22222222 33333333) do ( echo ========== applying %%P ========== pushd D:\patch\%%P call %OPATCH% apply -silent if errorlevel 1 ( echo [FAILED] patch %%P, abort popd goto :eof ) popd ) echo ALL PATCHES DONE逻辑说明:pushd/popd保证每次循环都把工作目录切到对应补丁目录再切回,避免目录串位;call调用.bat形式的 opatch 是必须的,直接写路径执行会导致批处理提前退出;if errorlevel 1捕获非零退出码后立刻中止,不允许"带着失败继续打下一个",因为后面的补丁可能依赖前面已经落地的文件。
-silent只是收敛输出,不影响退出码,这一点可以放心。每次循环打印的补丁号建议和D:\patch\下的实际目录名核对一遍,别让批处理里的列表和磁盘上的目录对不上。
5. 避坑与排查:五个把库打挂或打到一半卡住的场景
这一节按"现象、原因、解决"的结构记,都是现场真实遇到过的类型,顺序大致按出现频率排。
5.1 安装阶段:报错其实就那么几类
现象一:The patch location is not a valid patch area,退出码 73。原因:工作目录不在补丁包根层,常见于在D:\patch\这种父目录执行,或者解压时多套了一层文件夹。 解决:cd到能看到etc和files两个子目录的那一层再执行;如果解压出来是11111111\11111111\etc这种双层结构,把内层提上来或者直接cd到内层。
现象二:OPatch version ... is not supported或补丁包里自带的opatch和 home 里的版本不一致。原因:没有先升级 OPatch,或者升级时解压层级错了,OPatch目录套了OPatch\OPatch。 解决:%ORACLE_HOME%\OPATCH\opatch version确认版本,不对就重新覆盖;覆盖前把老目录改名备份,别直接删。
现象三:Prerequisite check "CheckActiveFilesAndExecutables" failed。原因:还有进程占着ORACLE_HOME下的文件,通常是实例没停干净或者服务还在跑。 解决:tasklist | findstr /i oracle逐个确认,必要时把OracleService<SID>也停掉再重试;不要用强杀进程的方式绕过,被杀进程持有的文件句柄释放不干净,反而更容易留下半截状态。
现象四:Patch ... is already installed。原因:lsinventory里已经有这个补丁号,重复执行。 解决:先opatch lsinventory确认,确实已装就跳过;如果怀疑上次打到一半失败但登记了,用opatch rollback -id <补丁号>清掉再重来,别硬 apply。
5.2 启动阶段:库起来了不等于补丁生效
现象五:所有补丁都显示 succeed,重启后库能起,但应用报一堆视图失效、包编译不过。原因:二进制补丁落地了,但数据字典没有跟着更新。11.2 的补丁机制里,ORACLE_HOME层面的文件替换只是第一步,字典侧还要跑一遍更新脚本把新增的视图、包、权限刷进去,否则 SQL 层看到的还是旧定义。 解决:按补丁 README 的说明,以 sysdba 身份执行字典更新和重编译:
-- 切到 admin 目录后执行,psu 参数按补丁类型选择,以 README 为准 sqlplus / as sysdba @?/rdbms/admin/catbundle.sql psu apply -- 编译所有失效对象,跑完再看 dba_objects 里的 invalid 数量 @?/rdbms/admin/utlrp.sql -- 确认无效对象是否归零 select count(*) from dba_objects where status = 'INVALID';catbundle.sql这个脚本会把补丁带来的字典变更登记到registry$history里,跑没跑过,查一下那张表就知道,比翻日志快。
现象六:重启服务器后 Oracle 服务没自动起来。原因:Windows 服务的启动类型不是"自动",或者补丁过程中服务被改成手动。 解决:services.msc里把OracleService<SID>和监听服务的启动类型设为自动,或者用sc config OracleServiceORCL start= auto改,改完手动起一次确认能起。
现象七:apply 中途断电或被人为中断,再执行报状态不一致。原因:补丁文件拷了一部分,inventory 没写完,处于中间态。 解决:先opatch lsinventory看有没有半登记,再opatch rollback -id尝试回退到干净状态;回退不了就按 README 的手工恢复步骤,或者直接用第 3 章的冷备整体还原。这种场景下冷备是唯一的后悔药。
6. 打完之后怎么验证:三条查询加一次回滚演练
补丁打完、库起来了、应用连上了,很多人到这就收工。我一般还会做一轮验证,因为"能连上"和"补丁真的生效"是两件事。
第一层验证在ORACLE_HOME侧,确认 inventory 登记正确:
rem 详细清单,包含每个补丁的时间戳和描述 %ORACLE_HOME%\OPATCH\opatch lsinventory -detail rem 与打补丁前的快照做对比,看新增了哪几行 fc D:\patch\lsinventory_before.txt D:\patch\lsinventory_after.txt第二层在数据库侧,确认字典侧也更新了:
-- 补丁登记历史,每跑一次 catbundle 就会多一条 select action_time, action, namespace, version, id from registry$history order by action_time desc; -- 组件版本,确认没有组件停留在旧版本 select comp_id, version, status from dba_registry;第三层是功能冒烟:挑几个核心业务视图和存储过程各查一次,确认没有ORA-04063之类的失效报错。
下面这张表是我实际会逐项过一遍的验证清单:
| 验证项 | 命令/位置 | 通过标准 |
|---|---|---|
| 补丁已登记 | opatch lsinventory -detail | 目标补丁号出现在列表 |
| 字典已更新 | registry$history | 有对应时间的 apply 记录 |
| 组件版本一致 | dba_registry | 各组件 status 为 VALID |
| 无失效对象 | dba_objects按 status 统计 | INVALID 数量与打补丁前持平或更少 |
| 监听正常 | lsnrctl status | 服务已注册、状态 READY |
还有一个动作我建议做,虽然它意味着要再停一次库:在测试环境完整走一遍opatch rollback。原因很简单,回滚命令平时没机会用,真出事的时候是第一次用,参数记错、顺序搞反都很正常。提前演练一次,把回滚耗时、回滚后要不要重跑utlrp.sql、回滚完应用能不能直接连上这些细节摸清楚,比在故障现场现查文档强太多。
rem 回滚演练,id 换成演练用的补丁号,生产环境谨慎执行 cd /d D:\patch\11111111 %ORACLE_HOME%\OPATCH\opatch rollback -id 11111111血泪经验是:第一次打 11.2.0.1 的补丁时,我以为succeed就是终点,重启后应用报了一屏ORA-04063,才回头去补catbundle.sql和utlrp.sql,中间多停了四十分钟。从那以后我每次打完补丁,都强制走一遍"lsinventory 对比 + registry$history 查询 + invalid 对象计数"这三步,一步不省,也一定把打补丁前的 lsinventory 快照和冷备路径写在变更单上。这份 doc 里把执行顺序和命令都按现场节奏排好了,需要的话在下载包里自取,对着敲一遍比临场拼命令稳得多。希望帮到你。
本文还有配套的精品资源,点击获取