☰
Oracle 11.2.0.4 RU补丁安装实战:从OPatch到字典脚本
2026/10/14 23:59:48 网站建设 项目流程

简介:该压缩包为Oracle数据库11.2.0.4.161018季度补丁资源共享包,面向Linux x86-64平台,对应补丁编号p24006111,主要服务于需要维护Oracle 11g生产环境的数据库管理员。补丁发布于2016年10月18日,属11g第二版的积累性季度更新,用于修复已知缺陷、加强安全防护并提供性能优化。压缩包整体约100.6MB,内含补丁信息XML说明文件与编号24006111的实际补丁二进制文件,文件级明细当前尚未收录。数据库管理员可通过Opatch工具完成补丁的验证、安装与回滚操作;应用前需备份数据库、核对系统兼容性并规划停机窗口。已有265人学习该资源,适合正在规划Oracle 11g补丁升级或需要了解季度补丁机制的DBA。理解补丁适用条件、安装步骤及潜在影响,是保障核心业务系统安全稳定运行的关键环节。

1. 看到 p24006111_112040_Linux-x86-64.zip:先读文件名的四个段,再决定动不动手

文件名本身就是安装手册的第一页。p 前缀是 Patch 的固定标识,24006111 是补丁号,112040 对应 11.2.0.4.0 版本简写,Linux-x86-64 锁定了平台,zip 是分发格式。把四个段拼起来,这是一份 11.2.0.4 的 RU(Release Update)补丁包,既带安全修复也带数据库核心组件的常规 bug 修复,和早年那种单发的小补丁不是一个量级的东西。这篇文章要解决的是这套文件怎么落地:解压、升级 OPatch、预检、停实例、apply、跑字典脚本、编译失效对象、最后验证,以及最容易翻车的几个环节。适合手头有 11.2.0.4 生产库或者测试库要跟上补丁节奏的 DBA,也适合刚接手老库、发现补丁欠了一屁股债的运维同学。

2. 解压与升级 OPatch:这两件事不做,后面 apply 大概率白跑

2.1 补丁号、版本段与平台段的含义

24006111 这个数字不是随机生成的,前几位是补丁序列号,整个号段对应 11.2.0.4 的 RU 序列。112040 段读起来是 11.2.0.4.0,注意这里的第四位是 0,表示基本安装版本就是 11.2.0.4,不需要先打别的补丁集。Linux-x86-64 不用多说,这个包只能用在 x86_64 架构的 Linux 上,平台不对硬解压只会浪费时间。我见过有人把 Linux 平台包解压到 AIX 主机上,opatch 直接拒绝读取 inventory,那才是真正的开头就翻车。

再说 RU 和 PSU 的关系。11.2.0.4 后期,修复包从传统的 PSU(补丁集更新)逐步过渡到 RU(版本更新),RU 里混合了安全修补和普通缺陷修复,发布日期有节奏,不是等某个严重 bug 攒够了才发。所以看到 24006111 这种 RU 补丁,别以为它只是某个 bug 的专项修复,它是一整批变更的合集,安装完必须走完整的字典脚本阶段。

2.2 解压、完整性校验与磁盘空间评估

解压不是unzip一下就行。补丁包内部是一个目录树,包含 p 码子目录、README、以及 OPatch 需要读取的 meta 文件。我习惯先把补丁包放到独立的补丁目录下,再解压到以补丁号命名的子目录,这样后面 apply 时工作目录不会搞混。

PATCH_DIR=/u01/app/oracle/patch mkdir -p $PATCH_DIR/24006111 cd $PATCH_DIR unzip -q p24006111_112040_Linux-x86-64.zip -d 24006111 unzip -t p24006111_112040_Linux-x86-64.zip | tail -5 du -sh 24006111 df -h $PATCH_DIR

-q是静默解压,避免几百个文件刷屏;-d指定解压目标目录,不指定的话 zip 里的内层目录名会直接散落在当前目录,很乱。-t参数是测试压缩包完整性的,输出最后几行能确认没有 CRC 错误。du -sh看解压后实际占用,df -h确认磁盘剩余空间,补丁解压和安装过程需要的空间至少是补丁包体积的两倍,因为在 apply 过程中 OPatch 会在 ORACLE_HOME 下写中间文件。

解压到这里不算完。如果这个 zip 是从镜像站点或者内部共享盘拷过来的,传输过程可能出错,建议再做一次校验。

cksum p24006111_112040_Linux-x86-64.zip md5sum p24006111_112040_Linux-x86-64.zip

把输出的值跟补丁发布说明里给的值比对。文件校验和丢了,补丁装到一半报出来某个文件损坏,那时候再回头找原因,代价是重跑一遍整仓安装流程。

2.3 OPatch 版本核对与升级步骤

11.2.0.4 的补丁对 OPatch 工具有最低版本要求,这个要求写在补丁包自带的 README 或者补丁说明文档里。先看一下当前环境是什么版本。

export ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1 export PATH=$ORACLE_HOME/OPatch:$ORACLE_HOME/bin:$PATH opatch version

如果环境是多年没动过的老库,OPatch 很可能停留在很早的版本,这时候就要先升级 OPatch。升级本身不复杂,就三步:备份旧的、解压新的、确认版本。

mv $ORACLE_HOME/OPatch $ORACLE_HOME/OPatch.bak_$(date +%Y%m%d) unzip -q opatch_update.zip -d /tmp/opatch_update cp -r /tmp/opatch_update/OPatch $ORACLE_HOME/ chown -R oracle:oinstall $ORACLE_HOME/OPatch opatch version

上面的opatch_update.zip是泛指新版本 OPatch 的分发包,具体文件名以下载到的为准。备份旧目录这一步别省,新版 OPatch 万一在这个环境下水土不服,把OPatch.bak_*改回去就能恢复。注意整个操作都要用安装数据库时创建的那个系统用户执行,一般是 oracle 用户,绝对不要在 root 下解压或者赋权,否则 ORACLE_HOME 属主一乱,后面 opatch 读写 inventory 全是权限报错。

3. 安装前的先决条件:三条命令决定能不能一次通过

3.1 检查当前补丁历史与已装组件

apply 之前先把家底盘清楚。第一个要确认的是这个补丁是不是已经装过,第二个是当前 ORACLE_HOME 里有没有一堆临时补丁(interim patch)跟 RU 冲突。

cd $PATCH_DIR/24006111 opatch lsinventory > /tmp/lsi_before_patch.txt grep -i "24006111" /tmp/lsi_before_patch.txt grep -i "interim patch" /tmp/lsi_before_patch.txt

opatch lsinventory输出当前 ORACLE_HOME 下所有已应用的补丁记录。第一条 grep 看补丁是否已经在列表里,如果在,apply 会被拒绝;第二条 grep 看有没有临时补丁,临时补丁多的时候要先逐个做冲突评估,不能直接往下走。检查完的文本记得保留,后面写变更记录和回滚依据都要用它。

3.2 生成 OCM 响应文件

11.2.0.4 的 opatch 在 apply 时需要读取 OCM(Oracle Configuration Manager)相关的配置响应文件,不提供的话命令会停在交互输入,在无人值守环境里看起来就像卡死了。预先把它生成好,后面不管是干跑还是正式跑都用得上。

$ORACLE_HOME/OPatch/ocm/bin/emocmrsp -no_banner -output /tmp/ocm.rsp

-no_banner去掉版权信息输出,-output指定生成路径。运行过程中会问几个问题,一般直接回车默认即可。这个文件生成一次就能反复用,不涉及什么敏感配置,放心留在 /tmp 下。

3.3 冲突预检与 apply 干跑

接下来是 repeat 的两条命令,一条做冲突检测,一条做全流程预演。

cd $PATCH_DIR/24006111 opatch prereq CheckConflictAgainstOHWithDetail echo "prereq exit code: $?"

CheckConflictAgainstOHWithDetail检查补丁要覆盖的文件和当前 ORACLE_HOME 里已安装补丁覆盖的文件有没有交集。有交集说明两个补丁碰了同一个文件,不处理就 apply,轻则装不上,重则文件覆盖顺序出错导致二进制损坏。返回码是 0 才代表通过。

冲突检查过了,再做一次真正的干跑:

opatch apply -dryrun -silent -ocmrf /tmp/ocm.rsp echo "dryrun exit code: $?"

-dryrun会把从读补丁包、生成 apply 计划、校验文件列表到模拟写入的全部流程走一遍,但不实际改系统。-silent是非交互模式,配合-ocmrf指定响应文件,严格来说干跑加不加-silent都行,但正式跑时一定要带,养成习惯两个命令保持一致,少踩一次交互卡住的坑。干跑通过后,正式开始前再快速核对一遍环境变量和用户身份,避免细节翻车。

env | grep -E "ORACLE_HOME|ORACLE_SID|PATH" id ls -ld $ORACLE_HOME | awk '{print $3}'

这三行分别确认:环境变量指向正确、当前用户是 oracle 同权限用户、ORACLE_HOME 属主确实是当前用户。任何一条不对,apply 跑起来就是权限或路径错误,而且报错信息经常模棱两可。

下面把预检的关键项整理成一张表,方便贴在变更记录里。

检查项命令通过标准
OPatch 版本opatch version等于或高于补丁要求版本
补丁是否已装opatch lsinventory列表中没有 24006111
临时补丁冲突opatch prereq CheckConflictAgainstOHWithDetailexit code 为 0
OCM 响应文件emocmrsp文件生成且非空
完整流程预演opatch apply -dryrunexit code 为 0
用户与属主id、ls -ld ORACLE_HOME当前用户与属主一致

4. 正式安装:停库、apply、字典脚本三步衔接

4.1 干净停库与关键文件备份

RU 补丁的 apply 阶段要求实例必须全部关闭,因为它在替换二进制文件,运行中的进程会占用文件句柄,opatch 根本写不进去。停库用 immediate 级别最合适,干净且有回滚事务的机会,除非库本身有问题,否则别用 abort。停库之前记录一下当前日志切换状态,顺手做一次日志切换,对后续恢复更友好。

sqlplus / as sysdba SQL> archive log list; SQL> alter system switch logfile; SQL> shutdown immediate; SQL> exit

shutdown immediate会等待未提交事务回滚后关闭,时间取决于回滚量,正常库也就几秒到几十秒。退出后用进程检查确认实例真的没了:

ps -ef | grep smon | grep -v grep

没有输出就是干净了。有些环境有多个实例,或者装了 ASM,要确认没有其他数据库进程还挂着,opatch 不关心别的实例,但你的 ORACLE_HOME 如果被多个实例共用,所有实例都要停掉。

这个阶段顺手做文件备份,备份对象是 dbs 目录、网络配置文件、以及数据库初始化参数文件。

mkdir -p /u01/app/oracle/backup/patch_$(date +%Y%m%d) cd /u01/app/oracle/backup/patch_$(date +%Y%m%d) cp $ORACLE_HOME/dbs/init*.ora . cp -r $ORACLE_HOME/network/admin . cp /tmp/lsi_before_patch.txt .

这些文件是回滚时最常需要比对的东西,几十 KB 占不了空间,但没备到时真要找就费劲了。有条件的环境会把整个 ORACLE_HOME 打包,比如 tar 到本地另一个磁盘,但那需要两倍于 ORACLE_HOME 的磁盘空间,不是所有机器都放得下,按实际条件取舍。

4.2 阅读 README 并执行 opatch apply

正式 apply 之前,必须先看补丁包里 README 写的 postinstall 要求。RU 补丁和以前的小补丁不同,光 apply 完二进制不算完,后面还要跑字典脚本,脚本名和参数以 README 为准。这个步骤网上能找到各种二手说法,版本一换就失效,看包里的原文最稳。

cd $PATCH_DIR/24006111 ls -F cat README.txt | less

ls -F能直观看到补丁包内有哪些子目录和文件,README 一般就在根目录。先花五分钟读完再动手,比装完发现少跑一步再回头补救划算得多。

正式安装命令和干跑只差一个参数:

opatch apply -silent -ocmrf /tmp/ocm.rsp echo "apply exit code: $?"

-silent保证全程无交互,输出会滚动显示正在执行的动作和日志路径。apply 跑完要看两处:屏幕最后一行是成功的确认信息;退出码是 0。别看到一堆滚动输出就以为成功了,确认退出码和最后的成功提示才算数。

apply 阶段生成的详细日志在 ORACLE_HOME 下的.patch_storage目录里,这个目录以后回滚还要用,千万别手工清理。日志文件名带时间戳和补丁号,找最近生成的那个看报错就能定位问题。apply 过程中如果出现 ORA- 类错误,常见原因就是实例没停干净或者磁盘满了,先看 df,再看 ps,最后看日志。

4.3 启动到 upgrade 模式执行字典脚本

apply 完成后二进制已经替换成新版本,但数据字典还是旧的,这时候必须启动数据库到 upgrade 模式,执行补丁对应的字典更新脚本。11.2.0.4 的 RU 常见做法是跑 rdbms/admin 下的 catbundle.sql,具体参数按 README 来。有的补丁需要带参数,比如传 psu 或 cpu,有的脚本能自动识别,以包内说明为准。

sqlplus / as sysdba SQL> startup upgrade; SQL> @?/rdbms/admin/catbundle.sql psu SQL> shutdown immediate; SQL> startup;

startup upgrade是以升级模式打开库,会禁用一部分普通运行时的功能,防止低版本会话干预字典变更。catbundle.sql 脚本执行时间取决于库的大小和组件数量,可能十几分钟也可能更久,耐心等它跑完,期间观察终端有没有报错堆积。脚本结束后必须 shutdown 再 startup,用普通模式把库拉起来,因为 upgrade 模式下很多东西不可用,直接留在 upgrade 模式跑后续编译脚本会出奇怪的问题。

字典脚本跑完之后编译失效对象是规范动作。数据库刚经历大批量的系统对象替换,视图、包、过程都会处于 invalid 状态,不编译的话业务一跑就是报错。

SQL> @?/rdbms/admin/utlrp.sql

utlrp.sql 是数据库自带的 PL/SQL 重编译脚本,它会以多线程方式扫描所有失效对象并逐个重编译,编译完再扫一遍残留的。脚本本身可以重复执行,第一次跑完发现有零星对象还失效,再跑一次通常就干净了。但要注意它必须在普通 startup 模式下跑,不能继续留在 upgrade 模式。

编译完成后查一次失效对象总数,心里先有个底:

SQL> select count(*) from dba_objects where status='INVALID';

预期结果是 0,或者少量系统对象残留。残留数量多的话,先查类型和所属 schema,如果是大量业务 schema 下的对象失效,大概率是字典脚本没跑完或者顺序不对,不要急着逐个手动编译,先排查根本原因。

4.4 多实例集群环境注意流程差异

如果是多实例集群环境,每个节点的二进制都要 apply,但字典脚本只在其中一个节点执行。节点多的时候每个节点都完全关闭运行防串扰,但也可以逐个节点滚动,先停一个节点、在该节点 apply、再启动该节点,逐个处理,业务不中断。这个操作手法比较讲究,一般建议每个节点都做完整的停库、apply、启库流程,数据库 failover 能力由集群软件保证。需要特别提醒的是字典脚本执行时,要确保当前执行的节点能访问到共享存储的数据库,且其他节点不能同时跑在线 DDL,具体以集群环境和补丁 README 为准,别拿单机经验硬套多点环境。

5. 安装后的常见翻车点:五条踩坑记录与排查命令

5.1 现象:opatch apply 刚开始就退出,提示有数据库实例在运行

原因:ps -ef | grep smon | grep -v grep那一步偷懒没做,或者做的时机不对,实例还在进程列表里就启动了 opatch。解决:回到 SQL*Plus 里执行shutdown immediate,然后确认进程消失,再重跑 apply。注意 shutdown 之后等几秒让进程完全释放,别着急离开终端。多实例环境还要把该 ORACLE_HOME 下所有实例都停掉,漏一个就报同样的错。

5.2 现象:prereq 检查报 OPatch 版本不足,或者 opatch version 显示的不是当前版本

原因:PATH 里把别的目录的 OPatch 放在了前面,常见是/usr/bin下也有一个 opatch,或者环境变量 ORACLE_HOME 指向了客户端安装目录。解决:先which opatch看命中的是哪个路径,再用opatch version确认实际版本。如果确实版本太低,回头执行第 2 章的升级步骤,升级完重新跑 prereq,不要绕过检查硬 apply。

5.3 现象:apply 卡在 Configuration 阶段不动,像死了一样

原因:11.2.0.4 的 opatch 需要读 OCM 响应文件,没给它就在标准输入上等着输入,在人眼看来就是卡死。解决:中断后执行$ORACLE_HOME/OPatch/ocm/bin/emocmrsp -no_banner -output /tmp/ocm.rsp生成响应文件,然后带-ocmrf /tmp/ocm.rsp重跑 apply。这个坑在无人值守时最坑,看起来像挂起,实际上只是等输入。

5.4 现象:库起来了,业务报 ORA-04063,查询失效对象还有几十个

原因:catbundle 字典脚本没有完整执行完,可能是期间中断,或者 utlrp 在 upgrade 模式下跑,脚本根本没编译到那些对象。解决:先查dba_registry_history确认字典变更是否记录在案,然后重启到 normal 模式重跑utlrp.sql。如果重跑还有残留,单独选中失效对象执行手动编译:alter package schema.xxx compile;,不要一次全库跑。空间不足也会让重编译半途而废,注意临时表空间的使用率。

5.5 现象:想回滚补丁,opatch rollback 却找不到 rollback 脚本

原因:RU 补丁的回滚脚本存放在 ORACLE_HOME 下的.patch_storage目录里,这个目录被手工清理过,或者 ORACLE_HOME 整个就有过迁移,元数据对不上。解决:二进制层面的 rollback 依赖这个目录,目录没了只能重新解压补丁包并重建元数据后尝试;而字典层的变更根本不是 opatch rollback 能撤销的,需要单独的降级脚本。这就是为什么我一直强调:补丁前必须有一个可以恢复全库的手段,RMAN 备份也好,存储快照也好,至少有一种,否则 RU 安装后的后悔药可能吃不回来。最稳妥的做法是把补丁前的关键文件和备份基线放到变更记录里留档。

6. 验证补丁生效:三层确认与收尾习惯

验证补丁生效不能只看 opatch 的输出,分三层确认更稳。第一层是文件层,库正常启动后重新执行补丁清单,确认补丁在列表里且状态正确。

opatch lsinventory | grep -i "24006111"

第二层是字典层,查数据字典的补丁历史表,确认字典变更已经在库里留下记录。

select action, version, namespace, action_time from dba_registry_history order by action_time;

查询结果里能看到补丁对应的记录行,说明 catbundle 那一步确实写进去了。只看 opatch 列表不看这层,万一字典脚本没跑成功而你没发觉,后面要花几倍时间来排查。

第三层是运行层,确认失效对象归零或者保持在可接受范围。

select count(*) from dba_objects where status='INVALID';

三层都确认完,收尾时我把这几样东西归档到变更记录目录里:补丁前的 lsinventory 输出、补丁后的 lsinventory 输出、apply 日志路径、这次补丁对应的回滚依据。补丁包和解压目录保留到下一个补丁验证通过之前。.patch_storage目录不动。环境台账里更新一行:24006111 已应用,应用时间、操作人、回滚方式。我自己的习惯是每次打完补丁,在笔记本上写一行字:补丁号、ORACLE_HOME、日志位置、回滚依据,下次再碰这环境不用翻一个月前的终端记录。这套流程走下来,补丁这事就闭环了,希望对你有帮助。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询