☰
Oracle 11.2.0.4 PSU补丁应用与回滚实战全指南
2026/10/13 0:56:55 网站建设 项目流程

简介:适用于Linux x86-64平台的Oracle 11g R2补丁包,编号p26635834,面向数据库运维与管理人员,用于修复已知安全漏洞、性能问题并提升系统稳定性。压缩包共103个文件、40.49MB,以64个class字节码、17个SQL脚本、7个XML配置、5个JAR包为主体,辅以SSL证书、HTML说明和归档包,可覆盖补丁元数据校验、数据库对象更新及安全配置等环节。已有265人学习下载,适合需要维护Oracle数据库并快速应用官方补丁的技术人员。包内含PatchSearch.xml补丁元数据与26635834补丁内容,使用OPatch工具即可完成环境检查、应用和验证;通过class和JAR可定位模块变更逻辑,SQL与XML则帮助核对脚本执行内容,便于在测试环境先行验证后再推向生产。及时部署此类补丁能显著降低安全风险,保障企业级数据库长期健康运行。

1. 二十六位编号背后:这个补丁包能替生产库挡下哪些事

在 Linux 服务器上看到一个以 p 开头的 zip 包,很多人第一反应是解压、找 readme、按安装向导走。但p26635834_112040_Linux-x86-64.zip并不是一个普通安装包:它是 Oracle 11.2.0.4 数据库在 64 位 Linux 平台上的补丁包,编号 26635834 是补丁的唯一身份,112040 对应 11.2.0.4.0。这类 oracle 补丁的坑在于,它改的不只是二进制文件,还会动数据字典和运行时行为,打错、漏打、顺序反了都会让生产库进入一种「说不上坏、但就是不对劲」的状态。这篇文章把它的内容结构、停机窗口、应用步骤、回滚思路和排错经验一次讲透,适合手里维护着 11g 环境、正准备做季度补丁升级的运维和 DBA。

2. 补丁结构:读懂编号和解压目录,少踩一半的坑

2.1 编号里的信息:p26635834、112040、Linux-x86-64 分别代表什么

Oracle 补丁 zip 的命名规则相当统一。p后面跟 8 位数字,是补丁号,每个补丁号在发布体系里唯一,后续的 PSU、Bundle Patch 都会用这个号作为身份标识。112040拆开是 11.2.0.4.0,指向数据库主版本。Linux-x86-64限定了平台,说明这套二进制只能在 64 位 Linux 的 x86_64 架构上运行,拿到 Solaris 或 AIX 上解压安装一定会失败,因为 zip 包里装的是编译好的目标文件,不跨平台通用。

补丁号大小并不代表版本新旧,它只是流水号。实际判断这套补丁覆盖到什么级别,要看 README 里的「Applicability」段落,它通常会写「适用于 11.2.0.4 的哪些基准版本,需要先安装哪个 OPatch 版本」。我有一次图省事,没看这段直接执行 opatch apply,结果它先检查 OPatch 版本,卡在一个「版本过旧」的提示上,临时去升级 OPatch 又花了半小时。所以拿到 zip 的第一步,不是解压,而是先看补丁说明里对前置环境的要求。

还有一点容易忽略:11.2.0.4 的补丁有些是针对数据库软件本身的,有些是针对 Grid Infrastructure 的,两者安装路径不同,绝不能混用。这份p26635834是数据库侧补丁,消费者是$ORACLE_HOME,不是$GRID_HOME,这点在动手前就要确认清楚。

2.2 补丁类型:PSU、Bundle Patch、one-off 怎么选

生产环境最常见的补丁形式有三种:PSU(Patch Set Update)、Bundle Patch、one-off 补丁。核心区别在于发布节奏和影响范围。

类型发布节奏包含内容适用场景
PSU每季度安全修复 + 关键 bug 修复,累积式常规生产环境首选
Bundle Patch按平台打包在 PSU 基础上合并平台特定修复云环境、一体机环境
one-off不定针对单个问题紧急修复某个具体 bug

我的习惯是生产库尽量只碰 PSU 和 Bundle Patch,不随便打 one-off。原因是 one-off 补丁往往要求当前补丁级别与它严格匹配,打到一半发现和已有 PSU 冲突的案例并不少见,最后要么回滚要么先升级补丁级别,变更窗口被拖长。PSU 是累积的,最新 PSU 包含之前所有 PSU 的内容,所以从旧基准直接打最新 PSU 就行,不需要先打中间版本。

这套p26635834走的就是 PSU 语义。也就是说,如果你的库之前已经打了 2015 年、2016 年的 PSU,这份新补丁会直接覆盖并超越它们的修复内容,不会要求你先卸载旧的再装新的。这个特性对生产环境特别友好,也让补丁记录看起来更干净。

2.3 解压之后:目录结构、文件作用与校验

$ unzip -q p26635834_112040_Linux-x86-64.zip -d /u01/app/oracle/patch/ $ cd /u01/app/oracle/patch/26635834 $ ls -la drwxr-xr-x 5 oracle dba 4096 ... etc drwxr-xr-x 3 oracle dba 4096 ... files -rw-r--r-- 1 oracle dba ... README.txt $ md5sum -c MD5.txt # 若包内附带校验文件

unzip -q的-q参数让解压过程只输出错误,避免大量文件名刷屏;-d指定解压目标目录。解压后你会看到一个以补丁号命名的目录,里面README.txt是最高优先级文件,every步骤的最终解释都以它为准。files目录存放编译好的二进制目标文件、SQL 脚本和可执行文件;etc目录是 OPatch 的 Action 描述,opatch apply 时就是按这里的配置决定替换哪些文件、执行哪些操作。

我不建议跳过校验这一步。下载链路越长,文件损坏的概率越高,一张校验值对不上就能避免后面一整晚的折腾。用md5sum -c时注意路径要和校验文件里记录的路径一致,不一致会报「no properly formatted MD5 checksum lines found」,这时需要切到校验文件所在目录再执行。若 zip 内没附带校验文件,就去下载页面核对官方校验值,手动比对。

2.4 配套组件:OJVM 补丁容易漏

11.2.0.4 的 PSU 还有一个容易漏掉的部分:OJVM 补丁。纯数据库 PSU 通常不包含 Oracle Java VM 的修复,如果你的库启用了 Java 组件(比如跑了 Java 存储过程、APEX 相关功能),打完这份补丁后,dbms_java相关的内容依然停留在旧级别。发布方一般会同期提供一个配套的 OJVM 补丁包,需要在 README 指定的顺序下应用。

我见过不止一个人只打了数据库 PSU,没打 OJVM 补丁,安全检查时被问起组件版本才意识到漏了一半。验证方法很简单:opatch lsinventory看补丁列表里有没有 OJVM 字样,没有就是没打。这种事最好在变更记录里写清楚,后续审计时可以直接查到对应关系。

3. 打补丁前的必修课:备份、环境检查与回滚预案

3.1 备份策略:数据文件、ORACLE_HOME 与参数文件一个都不能少

很多从业者以为打数据库补丁只改软件,数据文件不受影响,所以只做软件备份。这是对补丁机制最大的误解。补丁里的 SQL 脚本会更新数据字典对象,包括视图、包、同义词和默认参数。一旦脚本跑到一半失败,或者数据字典与二进制版本不匹配,数据库会卡在一个既不能正常 open、又不能简单回退的中间态。所以数据备份永远排在第一位。

$ rman target / RMAN> backup database plus archivelog delete input; RMAN> backup spfile; $ tar -czf /backup/oracle_home_$(date +%Y%m%d).tar.gz $ORACLE_HOME

RMAN 备份是回滚的最后退路,plus archivelog会把归档日志一并备份,delete input表示备份完成后删除已归档日志,这个行为要和日常归档保留策略对齐,别顺手改变备份习惯。ORACLE_HOME 的 tar 打包是为二进制回退准备的,打补丁前把它压成一个带日期的包,万一 apply 阶段文件被改坏,直接用 tar 覆盖回去就能恢复软件层。$(date +%Y%m%d)自动生成日期后缀,避免覆盖历史备份。

参数文件必须单独备份。补丁脚本有时会更新spfile里的默认参数,回滚时需要知道哪些参数是被补丁动过的。backup spfile一条命令就能解决,不要省。备份目录建议放在和 ORACLE_HOME 不同的磁盘上,防止同一块盘故障时两头都丢。

3.2 环境检查清单:版本、空间、inventory 三条线

检查项命令期望结果
ORACLE_HOME 路径echo $ORACLE_HOME与实际安装路径一致
OPatch 版本$ORACLE_HOME/OPatch/opatch version不低于 README 要求
磁盘空间df -h /tmp /u01剩余空间不小于补丁体积 1.5 倍
inventory 状态opatch lsinventory -detail能完整列出已安装补丁且无报错
数据库版本select * from v$version;11.2.0.4.0

多套环境共存一台机器时,环境变量串味是最常见的翻车点。我一般会在执行前把 ORACLE_HOME、ORACLE_SID、PATH 三行直接打印出来逐项确认,不信任任何人的口头承诺。

$ source /home/oracle/.bash_profile $ echo "HOME=$ORACLE_HOME SID=$ORACLE_SID" $ which opatch sqlplus $ $ORACLE_HOME/OPatch/opatch lsinventory -detail 2>&1 | tail -30

which opatch用来确认调用的是不是$ORACLE_HOME下的可执行文件,避免 PATH 里混进另一套数据库的 OPatch。lsinventory -detail会把当前 home 已安装的补丁全部列出来,如果这里报错或列不出来,意味着 central inventory 可能损坏,后面所有 opatch 操作都会受阻。遇到这种情况不要硬打补丁,先把 inventory 修好再继续。

3.3 停机窗口与回滚预案:把「后悔药」准备在前面

打补丁不是两分钟的事。从关闭监听、关闭实例,到 opatch apply,再到以 upgrade 模式启动、跑 SQL 脚本、重新启动,一个中等负载的库整个窗口按两到四小时规划比较稳妥。如果数据库还承担着批处理任务,窗口要避开月末月初。RAC 环境还要额外考虑逐节点滚动的时间。

回滚预案要在变更单里写明两条路径:若 SQL 脚本还没执行,直接opatch rollback回退二进制;若脚本已经跑了一半,先处理数据字典回滚,再做二进制回滚。这两条路的具体命令在第 6 章给。这里重点是把「做到哪一步算成功、哪一步算失败、什么条件下放弃」提前写清楚,避免出问题时边查资料边做决定。

窗口规划还要考虑 SQL 脚本的执行时间。startup upgrade模式下跑数据字典脚本,小库可能十分钟,大库可能超过一小时,这段时间实例对外不可用,评估窗口时要把这段算进去,而不是只算 opatch apply 的十几分钟。

3.4 备库与 RAC 的特殊准备

如果架构里有 Data Guard,备库要打同一套补丁,顺序通常是先备库后主库,主备切换时两侧补丁级别一致才不会出兼容性问题。备库打补丁的流程和主库一样,同样要跑 SQL 脚本,只是可以先以备库模式启动验证。主库打完、备库也打完后,记得重新检查 DG 同步状态,补丁造成的参数变更有可能影响同步行为。

RAC 环境则建议逐节点进行:停掉一个节点的实例与监听,应用补丁,启动该节点,验证无误后再操作下一个节点。前提是补丁 README 明确支持滚动更新。11.2.0.4 的多数数据库 PSU 支持滚动,但每套补丁的说明会有差异,以 README 为准。若 README 没写滚动支持,就老老实实停全部节点一起打,别为了省窗口时间去赌兼容性。

4. 应用 p26635834:从预检到收尾的四步流程

4.1 预检:opatch prereq check 与 dry-run

$ cd /u01/app/oracle/patch/26635834 $ $ORACLE_HOME/OPatch/opatch prereq check -patchDir /u01/app/oracle/patch/26635834 -oh $ORACLE_HOME

prereq check会检查补丁是否适用于当前 home、有没有冲突补丁、是否缺少前置补丁。输出里有 Warning 和 Error 两类,Warning 可以不阻断,Error 出现后就不要继续 apply。很多新手看到 Warning 就慌,其实要看最后的 Summary 段,区分「可忽略」和「必须处理」。-patchDir指向解压出的补丁目录,-oh显式指定 ORACLE_HOME,比依赖环境变量更稳。

$ $ORACLE_HOME/OPatch/opatch apply -analyze -oh $ORACLE_HOME

-analyze做一次 dry-run,不会实际修改文件,只分析并输出将要变更哪些文件、是否有冲突。我习惯在正式 apply 前一晚先跑一次,把输出存档放进变更记录。注意这个动作会在临时目录生成分析文件,确认后要清理掉,否则下个月再来时容易把旧家当当成新生成的,干扰判断。

4.2 关闭实例与监听,确保进程彻底停止

$ lsnrctl stop $ sqlplus / as sysdba SQL> shutdown immediate; SQL> exit $ ps -ef | grep -E 'ora_|tnslsnr' | grep -v grep

shutdown immediate会等待正在执行的事务完成后关闭,如果业务还挂着长事务,这个过程会卡住一段时间。若超过预期时间可以改shutdown abort,但不建议在补丁窗口前使用,因为 abort 重启后需要实例恢复,反而拖长窗口。ps -ef检查是防止有遗留的后台进程或监听占着文件句柄,导致补丁覆盖二进制时报「Text file busy」。补丁更新的是正在被数据库使用的二进制文件,只要实例还开着,opatch apply 基本会失败。

注意sqlplus的路径必须来自目标环境的$ORACLE_HOME。如果登进去的是另一套环境的 sqlplus,关闭的可能不是你准备打补丁的实例,操作完才发现打错对象,这种事故在混合环境里出过不止一次。

4.3 正式执行 opatch apply

$ cd /u01/app/oracle/patch/26635834 $ $ORACLE_HOME/OPatch/opatch apply -silent -oh $ORACLE_HOME

-silent跳过交互确认,适合脚本化执行,日志默认写到$ORACLE_HOME/cfgtoollogs/opatch/下带日期的文件中。不加-silent走交互模式的好处是能逐步看到替换了哪些文件,坏处是挂终端时间长了容易断,会话一断 apply 进程就可能迷失方向。我习惯在 screen 或 tmux 里跑交互模式,完整保留输出。整个过程快的十几分钟,慢的半小时以上,取决于磁盘 IO。

-oh参数显式指定 home,前面已经提过,这里再强调一次。补丁应用期间不要开新的会话去操作这个 home 下的文件,避免文件句柄冲突。输出里出现「OPatch succeeded」才算成功,中途出现 warning 被忽略不代表失败,但要记录在案后续跟踪。

4.4 启动实例到 upgrade 模式并执行 SQL 脚本

$ sqlplus / as sysdba SQL> startup upgrade; SQL> @$ORACLE_HOME/rdbms/admin/catbundle_PSU_11_2_0_4_Linux_x86_64.sql SQL> shutdown immediate; SQL> startup

startup upgrade以受限模式打开数据库,让数据字典脚本可以修改系统对象。catbundle是标准 PSU 的 post-apply 脚本,作用是同步数据字典与二进制版本、重建失效对象、更新默认参数。注意脚本文件名可能随补丁不同而变化,准确名字以该补丁 README 的 Post-Installation 段为准,我这里给的是通用形式。

这段脚本可能跑 10 分钟到 1 小时,中途不要开别的会话往库里写数据。跑完后先shutdown immediate再正常startup,这样实例会以正常的读写模式启动,验证数据字典和二进制是否匹配。如果直接 startup 不加 shutdown,有些视图的状态缓存可能不完整,后续查询会得到误导性结果。

4.5 收尾验证:inventory、sqlpatch 与报警日志

$ $ORACLE_HOME/OPatch/opatch lsinventory -detail | grep -A2 26635834 $ sqlplus / as sysdba SQL> select patch_id, action, status from dba_registry_sqlpatch where patch_id=26635834; SQL> select count(*) from dba_objects where status='INVALID';

第一条命令确认 OPatch 层面已记录补丁;第二条确认数据字典侧已经应用,status应为SUCCESS;第三条检查失效对象数量。这里要注意,全库的失效对象不是为 0 就万事大吉,而是要和打补丁前的记录做对比,新增的失效对象才需要处理。

最后看一眼alert_<sid>.log尾部,确认没有 ORA-600 之类的新报错。习惯做法是把这三条命令的输出存成带日期的文本文件,放进补丁记录目录,以后回滚判断和审计时直接用,不用重新翻日志。

5. 常见问题与排查:打补丁翻车的六个真实场景

5.1 现象:opatch apply 报「prerequisite check failed」并退出

原因:多数是当前库已安装了某些 one-off 补丁,和 26635834 修改的是同一批文件,形成冲突;少数情况是 OPatch 版本过低,连检查脚本本身都跑不起来。

解决:先用opatch lsinventory列出当前已装补丁,把冲突补丁号记录下来,向补丁发布渠道确认处置方式;或按 README 要求升级 OPatch 后再重跑。不要为了绕过检查直接改参数强打,我见过这么操作的人,结果二进制被覆盖、inventory 与实际文件不匹配,后面连回滚都没法做。这种场景下最理智的做法是停止操作、记录现场、等待确认,而不是赌一把。

5.2 现象:补丁打完后 v$version 里看不到任何变化

原因:v$version显示的是数据库发行版本,不是补丁级别。PSU 的级别本来就不在该视图显示,拿它判断补丁是否生效,结论永远是「好像没打」。

解决:用opatch lsinventory和dba_registry_sqlpatch两个视角验证,一个管二进制层,一个管数据字典层。查询结果都对得上,补丁就是生效了,不需要再纠结版本号显示。以后判断补丁状态只看这两个地方,不要形成看v$version的习惯。

5.3 现象:startup upgrade 时 ORA-01092 或 ORA-00742 接连出现

原因:数据字典版本与二进制版本不一致,常见于 SQL 脚本执行中途断掉或漏执行,另一个可能是补丁有前置组件没装。这个场景最折磨人,因为它介于可开与不可开之间,数据库不是彻底崩溃,而是每次启动都报错回滚。

解决:先看 alert 日志最前面的报错,判断是缺对象还是版本不匹配。若是脚本断掉,回到 upgrade 模式重跑脚本;若是缺前置组件,需要先装对应前置再继续。如果两轮重跑都失败,别恋战,直接走恢复流程。我可以明确说,现场处理这种问题最有效的工具是补丁前的完整日志记录,没有记录就只能靠猜和试。

5.4 现象:opatch 提示 inventory 里不存在当前 ORACLE_HOME

原因:多套库共存一台机器,PATH 里的 opatch 和 ORACLE_HOME 不配对;或者 central inventory 记录损坏。后者在异常断电、手动删除过文件时更容易出现。

解决:确认 source 的是目标环境的 profile,再用readlink -f $ORACLE_HOME和cat $ORACLE_HOME/oraInst.loc核对安装路径。确认是 inventory 损坏,尝试通过 OUI 方式 attach home,不行再找 inventory 的备份恢复。不要尝试手动编辑 inventory 文件,文本格式稍有偏差就会引发新问题。

5.5 现象:apply 到一半提示「Text file busy」,进程退出

原因:数据库或监听进程没有完全停止,二进制文件被进程占用,Linux 拒绝覆盖。RAC 环境下还会出现集群资源未完全 offline 的情况。

解决:用ps -ef把ora_和tnslsnr相关进程都找出来,确认真停了再重新 apply。RAC 节点确认该节点的集群资源确实 offline。别图省事直接kill -9,除非能确认实例已经 crash,否则强杀进程可能损坏 SGA 或控制文件,引发更复杂的恢复工作。

5.6 现象:回滚也需要跑脚本,但不知道先跑哪个

原因:把二进制回滚理解成了唯一动作,忽略了数据字典侧的变更不会随二进制回退而自动撤销。补丁的 SQL 脚本已经修改了系统对象,不先回滚数据字典,二进制回退后会出现版本倒挂。

解决:正确顺序是先确认 SQL 脚本执行状态,查dba_registry_sqlpatch里的action字段。如果已执行,先把数据字典回滚脚本跑完,再做opatch rollback。如果脚本只跑了一半,甚至要先手动清理未完成的对象再回滚。这种复杂局面没有通用命令,只能靠变更记录按步骤还原。所以我反复强调打补丁时的输出要存档,回滚时它就是救命文档。

6. 验证与回滚:把补丁收尾做得像开头一样严谨

6.1 常规验证清单

验证面命令期望结果
补丁记录opatch lsinventory -detail包含 26635834,状态 applied
SQL 侧select * from dba_registry_sqlpatch;该行存在且 status=SUCCESS
对象状态select count(*) from dba_objects where status='INVALID';与打补丁前基线一致
日志alert 日志与 opatch 日志无 ORA-600、无 ERROR

这四个面全部过了,这次补丁变更才算真正闭环。我见过有人只查了第一条就宣布完成,结果数据字典脚本压根没跑,第二天业务侧报错才暴露。别省这一步,验证不是走形式,是给整个变更过程上保险。

6.2 回滚的正确姿势

$ sqlplus / as sysdba SQL> startup upgrade; SQL> @$ORACLE_HOME/rdbms/admin/catbundle_PSU_11_2_0_4_Linux_x86_64_rollback.sql SQL> shutdown immediate; SQL> exit $ $ORACLE_HOME/OPatch/opatch rollback -id 26635834 -oh $ORACLE_HOME

注意先后顺序:先回滚数据字典,再做二进制回滚。rollback同样要在实例停止状态执行,日志落在 OPatch 日志目录。回滚完成后,按 6.1 的清单再验一遍,确认补丁确实从两个层面都消失了。

经历过一次补丁事故之后,我给自己定了个强制流程:每次打完补丁,无论多晚,都要走一遍「lsinventory → sqlpatch → 无效对象对比 → alert 日志」四连查,输出存成带日期的文本,再清掉临时解压目录。这套动作看上去琐碎,却是整个补丁流程里最值得较真的部分,也是最容易在疲惫状态下被跳过的部分。从那以后,我所有经手的补丁变更再也没有出过「第二天业务报错」的状况。把这个习惯传给每个看你文章的人,希望帮到你。

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

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

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

立即咨询