简介:该资源为Oracle数据库11.2.0.4版本的Patch Set Update补丁包,补丁编号p33477185,发布于2022年1月,专为Linux x86-64平台设计,面向需要为Oracle 11g数据库打补丁的DBA与运维人员,用于修复安全漏洞、优化性能并解决已知问题。压缩包共含3658个文件,约436.52MB,以so动态库、o目标文件、xml元数据、sql脚本、plb与class等为主,另含jar、bin、sh及OPatch相关组件,覆盖补丁安装、验证与回滚所需的完整文件集。目前已有859人学习下载。包内PatchSearch.xml提供补丁元数据与安装指导,33477185文件为实际补丁程序,配合OPatch工具可完成解压、应用与验证;安装前需确认数据库版本兼容并做好备份,部分补丁需重启实例,安装后还应执行后置步骤并监控性能,适合需要保持数据库稳定与安全的读者参考使用。
1. 一次数据库补丁升级的完整复盘:从版本号到落地脚本
去年冬天,某公司一套核心业务库在凌晨两点告警,AWR 里一条 SQL 的执行计划突然从索引扫描变成全表扫描,业务侧响应时间从 80ms 飙到 4s。排查到天亮才发现,问题出在一个月前打的某个补丁上——当时只看了版本号对得上,没细究补丁引入的优化器行为变更。那次之后,我对任何数据库补丁包都多了一层敬畏:版本号只是入场券,真正决定成败的是补丁内容、前置条件和回退方案。
这次要拆的是DB-PSU-11.2.0.4.220118 (Jan 2022)-p33477185Linux-x86-64。从命名就能读出关键信息:这是 Oracle 11.2.0.4 版本的 PSU(Patch Set Update),发布日期 2022 年 1 月 18 日,补丁编号 33477185,面向 Linux x86-64 平台。它解决的是 11.2.0.4 这个经典版本在 2022 年初累积的一批已知问题,包括优化器修复、安全漏洞修补和少量功能性回退。适合谁用?还在维护 11.2.0.4 这套老版本、又不想大动干戈升级到 12c/19c 的团队——尤其是那些业务逻辑复杂、停机窗口极短、只能靠 PSU 续命的生产库。如果你正在找这个补丁的落地方法,或者打完之后遇到了 ORA- 报错,下面的内容应该能帮你少走弯路。
2. 补丁包结构拆解:README 里没明说的三个关键文件
拿到一个 PSU 压缩包,很多人第一反应是直接解压然后跑opatch apply。但 11.2.0.4 的 PSU 结构和 12c 以后不太一样,里面有几个文件决定了你能不能顺利打完。
2.1 目录布局与文件职责
解压p33477185_112040_Linux-x86-64.zip之后,典型结构是这样的:
33477185/ ├── README.html # 官方说明,包含前置补丁列表和已知问题 ├── etc/ │ └── config/ │ └── actions.xml # 补丁动作定义,opatch 靠它决定执行哪些脚本 ├── files/ │ ├── oracle/ # 实际替换的二进制和 SQL 文件 │ └── ... └── custom/ ├── pre/ # 前置脚本,打补丁前执行 └── post/ # 后置脚本,打补丁后执行README.html是必读的,但很多人只扫一眼版本号就关掉。里面有两个信息最容易被忽略:一是前置补丁列表(Prerequisites),11.2.0.4 的 PSU 通常要求先打上上一个季度的 PSU 或对应的 CPU;二是已知问题(Known Issues),比如某些补丁会导致catbundle.sql执行时间过长,或者需要额外设置_fix_control参数。
actions.xml是 opatch 的“黑匣子”。它定义了补丁会执行哪些 SQL 脚本、替换哪些文件、是否需要重启实例。如果你遇到OPatch failed with error code 73,多半是这个文件里某个动作的前置条件没满足。
custom/pre和custom/post目录下的脚本,是 DBA 最容易翻车的地方。pre里的脚本通常在补丁应用前运行,用来检查数据库状态;post里的脚本在补丁应用后运行,用来更新数据字典。这些脚本不会自动执行,需要你手动跑或者通过 opatch 的-invPtrLoc参数指定。漏跑post脚本的后果是:补丁显示打上了,但数据字典没更新,后续查询可能报ORA-00600。
2.2 版本号与补丁编号的对应关系
11.2.0.4.220118这个版本号拆开看:11.2.0.4是基础版本,220118是补丁发布日期(2022 年 1 月 18 日)。对应的补丁编号33477185是 Oracle 支持站点上的唯一标识。同一个基础版本可能有多个 PSU,比如11.2.0.4.210119和11.2.0.4.220118,它们的前置补丁要求不同。如果你从210119直接跳到220118,README 里可能要求你先打一个中间的 Merge Patch。
一个常见的误区是:认为 PSU 是累积的,打了最新的就不需要打中间的。实际上 Oracle 的 PSU 是增量累积的——每个 PSU 包含自上一个 PSU 以来的所有修复,但不包含上一个 PSU 之前的基础修复。所以如果你从11.2.0.4裸版本直接打220118,大概率会失败,因为缺少210119或更早的 PSU 作为前置。
2.3 校验和与解压注意事项
下载完成后,第一件事是校验文件完整性。Oracle 支持站点会提供 SHA-1 或 MD5 校验值,但很多人跳过这一步。如果压缩包在传输过程中损坏,解压时可能不报错,但opatch apply会报OPatch found the file ... is not a valid zip file。
# 校验 SHA-1(假设官方提供的值是 abc123...) sha1sum p33477185_112040_Linux-x86-64.zip # 对比输出是否与官方一致 # 解压时用 unzip -q 静默模式,避免输出太多干扰 unzip -q p33477185_112040_Linux-x86-64.zip -d /u01/patch/解压后检查33477185/README.html是否存在,以及etc/config/actions.xml是否可读。如果解压后目录名不是33477185,而是带额外后缀,opatch 可能找不到补丁定义。建议解压到独立目录,不要和之前的补丁混在一起,否则 opatch 可能加载错误的actions.xml。
3. 打补丁前的环境检查:五个必须确认的参数
补丁能不能打成功,八成取决于打之前的检查。11.2.0.4 这套老版本对环境尤其敏感,下面五个检查项是我每次必做的。
3.1 OPatch 版本与 Java 环境
11.2.0.4 自带的 OPatch 版本通常很老(比如 11.2.0.3.x),而220118这个 PSU 要求 OPatch 至少是11.2.0.3.20以上。检查方法:
# 查看当前 OPatch 版本 $ORACLE_HOME/OPatch/opatch version # 如果版本过低,需要先升级 OPatch # 下载 p6880880_112000_Linux-x86-64.zip(对应 11.2 的 OPatch 包) # 解压后替换 $ORACLE_HOME/OPatch 目录 mv $ORACLE_HOME/OPatch $ORACLE_HOME/OPatch_bak unzip -q p6880880_112000_Linux-x86-64.zip -d $ORACLE_HOME/Java 环境也容易出问题。OPatch 依赖 Java,如果$ORACLE_HOME/jdk下的 Java 版本和 OPatch 不兼容,会报OPatch failed to initialize。不要用系统自带的 OpenJDK,用 Oracle 自带的 JDK 最稳妥。
3.2 数据库实例状态与监听器
打 PSU 需要数据库处于关闭状态(对于非 RAC 环境),或者至少所有实例都停止。检查:
# 查看实例状态 sqlplus -S / as sysdba <<EOF select instance_name, status from v$instance; EOF # 如果 status 是 OPEN,需要先关闭 shutdown immediate; # 检查监听器状态 lsnrctl status监听器不需要关闭,但补丁应用过程中会重新编译一些二进制文件,如果监听器正在使用这些文件,可能导致OPatch报file busy。建议先停监听器,打完补丁再启动。
3.3 空间与权限检查
补丁解压后大约 1-2GB,加上备份空间,$ORACLE_HOME所在文件系统至少需要 5GB 空闲。检查:
# 查看 ORACLE_HOME 空间 df -h $ORACLE_HOME # 查看 inventory 目录权限 ls -ld $ORACLE_HOME/inventory # 确保 oracle 用户有读写权限如果inventory目录权限不对,opatch 会报OPatch cannot find the inventory。不要用 root 用户打补丁,用安装 Oracle 的那个用户(通常是oracle)。
3.4 前置补丁检查
前面提到,PSU 有前置补丁要求。检查当前已打的补丁:
$ORACLE_HOME/OPatch/opatch lspatches输出会列出所有已应用的补丁编号。对比README.html里的 Prerequisites 列表,如果缺少某个补丁,需要先打上。不要跳过前置补丁,否则opatch apply会在检查阶段直接失败。
3.5 备份:不是可选,是必须
打补丁前必须备份$ORACLE_HOME和数据库。$ORACLE_HOME的备份可以用tar:
# 备份 ORACLE_HOME(排除临时文件) tar -czf /backup/oracle_home_before_psu.tar.gz \ --exclude='$ORACLE_HOME/log' \ --exclude='$ORACLE_HOME/rdbms/log' \ $ORACLE_HOME数据库备份用 RMAN:
rman target / RMAN> backup database plus archivelog; RMAN> backup current controlfile;没有备份就不要打补丁。我见过太多因为没备份,打失败后只能重装数据库的案例。
4. 补丁应用与回退:opatch 命令的六个关键参数
环境检查通过后,就可以执行补丁应用了。这一章把opatch apply和opatch rollback的关键参数拆开讲。
4.1 opatch apply 的标准流程
进入补丁解压目录,执行:
cd /u01/patch/33477185 $ORACLE_HOME/OPatch/opatch apply如果一切正常,opatch 会输出类似:
Invoking OPatch 11.2.0.3.20 ... Patch 33477185 successfully applied.但实际生产环境中,很少一次成功。下面几个参数能帮你应对不同场景:
-invPtrLoc $ORACLE_HOME/oraInst.loc:指定 inventory 位置,当 opatch 找不到 inventory 时用。-jre $ORACLE_HOME/jdk/jre:指定 JRE 路径,解决 Java 兼容问题。-oh $ORACLE_HOME:显式指定 ORACLE_HOME,避免环境变量混乱。-silent:静默模式,适合脚本化执行,但出错时信息较少。-report:只报告不执行,用来预检查。-analyze:分析补丁冲突,打之前跑一遍能提前发现前置补丁缺失。
一个完整的预检查命令:
$ORACLE_HOME/OPatch/opatch apply -analyze -oh $ORACLE_HOME如果-analyze报错,先解决报错再正式打。
4.2 后置脚本执行与数据字典更新
补丁应用完成后,必须执行 post 脚本。11.2.0.4 的 PSU 通常需要在每个实例上运行catbundle.sql:
cd $ORACLE_HOME/rdbms/admin sqlplus -S / as sysdba <<EOF @catbundle.sql psu apply EOFcatbundle.sql会更新registry$sqlpatch和registry$history表,记录补丁应用历史。如果漏跑,opatch lspatches会显示补丁已打,但数据库内部不知道,后续查询可能报ORA-00600 [kqlPatchCheck]。
执行时间取决于数据库大小,小库几分钟,大库可能半小时以上。不要中途中断,否则数据字典可能处于不一致状态。
4.3 回退:opatch rollback 的正确姿势
如果补丁导致业务异常,需要回退。回退命令:
cd /u01/patch/33477185 $ORACLE_HOME/OPatch/opatch rollback -id 33477185回退后同样需要执行catbundle.sql的 rollback 版本:
sqlplus -S / as sysdba <<EOF @catbundle.sql psu rollback EOF回退不是万能的。如果补丁已经修改了数据字典,回退后可能残留一些对象。所以回退前最好用 RMAN 恢复到打补丁前的状态,而不是单纯依赖opatch rollback。
4.4 验证补丁是否生效
打完补丁后,用三个命令验证:
# 1. 查看 opatch 补丁列表 $ORACLE_HOME/OPatch/opatch lspatches | grep 33477185 # 2. 查看数据库补丁历史 sqlplus -S / as sysdba <<EOF select action, namespace, version, comments from registry$history; EOF # 3. 检查版本号 sqlplus -S / as sysdba <<EOF select version from v$instance; EOF如果registry$history里没有PSU记录,说明catbundle.sql没跑成功。
5. 避坑指南:五个让补丁失败的常见操作
这一章记录的是我踩过的坑,以及身边同行反馈的高频问题。每条按“现象 → 原因 → 解决”写。
5.1 ORA-00600 [kqlPatchCheck] 报错
现象:补丁打完后,某些查询报ORA-00600: internal error code, arguments: [kqlPatchCheck]。
原因:catbundle.sql没有在每个实例上执行,或者执行时数据库处于READ ONLY状态。11.2.0.4 的 PSU 要求catbundle.sql在READ WRITE模式下运行。
解决:确认数据库是READ WRITE,然后重新执行catbundle.sql psu apply。如果已经报错,可能需要先回退补丁,再重新打。
5.2 OPatch failed with error code 73
现象:opatch apply执行到一半报OPatch failed with error code 73。
原因:actions.xml里某个动作的前置条件不满足,常见的是缺少前置补丁,或者$ORACLE_HOME下某个文件被占用。
解决:查看$ORACLE_HOME/cfgtoollogs/opatch/下的日志,找到具体是哪个动作失败。如果是前置补丁缺失,先打前置补丁;如果是文件占用,停掉监听器和相关进程再试。
5.3 补丁打完后实例无法启动
现象:补丁应用成功,但startup时报ORA-01078: failure in processing system parameters。
原因:补丁可能修改了spfile或pfile的某些参数,或者$ORACLE_HOME/dbs下的文件权限变了。
解决:检查$ORACLE_HOME/dbs下的spfile和pfile,确认权限是oracle:oinstall。如果spfile损坏,用备份恢复,或者从pfile启动。
5.4 catbundle.sql 执行时间过长
现象:catbundle.sql跑了几个小时还没结束。
原因:数据库太大,或者registry$表被锁。11.2.0.4 的catbundle.sql在某些情况下会全表扫描registry$sqlpatch。
解决:检查是否有其他会话锁住了registry$表。如果有,先 kill 掉。如果只是慢,可以等,但建议在业务低峰期执行。
5.5 回退后数据字典不一致
现象:opatch rollback成功,但查询registry$history发现补丁记录还在。
原因:回退时没有执行catbundle.sql psu rollback,或者执行失败。
解决:手动执行catbundle.sql psu rollback,然后检查registry$history是否清除了对应记录。如果还不行,可能需要从备份恢复。
6. 进阶技巧:用脚本自动化补丁检查与验证
手动打补丁容易漏步骤,我后来写了一个检查脚本,每次打补丁前跑一遍,能省不少事。
6.1 补丁前置检查脚本
#!/bin/bash # pre_psu_check.sh - 打 PSU 前的自动检查 # 用法:./pre_psu_check.sh <ORACLE_HOME> <PATCH_ID> ORACLE_HOME=$1 PATCH_ID=$2 echo "=== 1. 检查 OPatch 版本 ===" $ORACLE_HOME/OPatch/opatch version echo "=== 2. 检查实例状态 ===" sqlplus -S / as sysdba <<EOF select instance_name, status from v\$instance; EOF echo "=== 3. 检查已打补丁 ===" $ORACLE_HOME/OPatch/opatch lspatches | head -20 echo "=== 4. 检查空间 ===" df -h $ORACLE_HOME echo "=== 5. 检查 inventory ===" ls -ld $ORACLE_HOME/inventory echo "=== 6. 预分析补丁 ===" cd /u01/patch/$PATCH_ID $ORACLE_HOME/OPatch/opatch apply -analyze -oh $ORACLE_HOME这个脚本把前面提到的检查项串起来,输出一目了然。如果第 6 步报错,说明前置条件不满足,先解决再打。
6.2 补丁后验证脚本
#!/bin/bash # post_psu_check.sh - 打 PSU 后的验证 # 用法:./post_psu_check.sh <ORACLE_HOME> <PATCH_ID> ORACLE_HOME=$1 PATCH_ID=$2 echo "=== 1. 检查 opatch 补丁列表 ===" $ORACLE_HOME/OPatch/opatch lspatches | grep $PATCH_ID echo "=== 2. 检查数据库补丁历史 ===" sqlplus -S / as sysdba <<EOF select action, namespace, version, comments from registry\$history where action like '%PSU%' or action like '%PATCH%'; EOF echo "=== 3. 检查版本号 ===" sqlplus -S / as sysdba <<EOF select version from v\$instance; EOF echo "=== 4. 检查无效对象 ===" sqlplus -S / as sysdba <<EOF select owner, object_name, object_type from dba_objects where status = 'INVALID' and owner not in ('SYS','SYSTEM'); EOF第 4 步很关键。补丁打完后,某些 PL/SQL 包可能变成INVALID,需要重新编译。如果无效对象太多,用utlrp.sql批量编译:
sqlplus -S / as sysdba <<EOF @?/rdbms/admin/utlrp.sql EOF6.3 参数对比表
下面这张表总结了opatch apply和opatch rollback的关键参数差异,方便查阅:
| 参数 | apply 用途 | rollback 用途 | 注意事项 |
|---|---|---|---|
-id | 指定补丁编号 | 指定补丁编号 | rollback 必须指定 |
-oh | 指定 ORACLE_HOME | 指定 ORACLE_HOME | 环境变量混乱时用 |
-invPtrLoc | 指定 inventory | 指定 inventory | 多 ORACLE_HOME 时用 |
-analyze | 预分析冲突 | 不支持 | 打之前跑一遍 |
-silent | 静默执行 | 静默执行 | 脚本化时用 |
-report | 只报告 | 只报告 | 不实际执行 |
6.4 一个容易忽略的细节:时区文件更新
11.2.0.4 的 PSU 有时会包含时区文件更新(tzdata)。如果数据库使用了TIMESTAMP WITH TIME ZONE类型,打完补丁后需要检查时区版本:
select * from v$timezone_file;如果版本和补丁要求的不一致,需要手动运行$ORACLE_HOME/rdbms/admin/utltz_upg_check.sql和utltz_upg_apply.sql。这个步骤在 README 里通常写在最后,容易被忽略,但漏掉可能导致时区相关查询报错。
从那以后我每次打 PSU,都会把pre_psu_check.sh和post_psu_check.sh跑一遍,确认每个环节都过了才放心。补丁这东西,不怕慢,就怕漏。希望帮到你。
本文还有配套的精品资源,点击获取