简介:面向Oracle 11.2.0.4数据库运维人员与DBA的一份重要补丁集更新(PSU),对应2022年1月发布的补丁编号p33477185,适用于Linux x86-64平台。该补丁包涵盖安全修复、性能优化及已知问题修复,可帮助用户保持数据库系统安全稳定运行。压缩包共3658个文件,类型以so共享库、o目标文件为主,辅以xml配置、sql脚本、jar组件及少量bin与plb等,分别用于补丁安装、配置校验和数据库对象更新;整体包体约436.52MB,内容结构清晰。已有850人学习/下载,可作为11.2.0.4版本定期维护、安全加固及补丁应用时的参考素材。包内同时包含PatchSearch.xml等元数据文件,便于核对补丁适用条件与安装信息,适合已具备Oracle基础运维能力、需要手动或借助OPatch完成补丁部署的读者使用。 从标题“DB-PSU-11.2.0.4.220118 (Jan 2022)-p33477185Linux-x86-64”能看出,这是一套 Oracle 11.2.0.4 在 Linux x86-64 平台上的 2022 年 1 月补丁集(PSU,Patch Set Update)。这个版本号在国内的存量数据库里保有量非常大,大量生产系统还跑在 11.2.0.4 上,而且很多是 Extended Support 阶段。这篇就结合我实际打补丁的经验,把从准备到验证的完整链路整理出来,重点讲那些看着简单、真做起来到处是坑的环节,以及每条命令背后为什么要这样执行。
1. P33477185 是什么:先搞懂你手上拿的这包东西
拿到补丁压缩包,先别急着解压,花两分钟看清楚包里到底是什么。P33477185 这个补丁号,对应的是11.2.0.4.220118 的 Database PSU,也就是 2022 年 1 月发布的 CPU(Critical Patch Update)内容。它的修复范围覆盖了数据库内核的多个安全漏洞和已知 bug,比如某些情况下 RAC 节点之间 IPC 通信异常、ASM 实例在特定版本下的内存泄漏问题等。对于还在 11.2.0.4 这个版本上的系统来说,这类 PSU 是保持安全和稳定的主要渠道。
这里有个容易混淆的地方:PSU 和 CPU 的关系。从 2012 年 10 月起,Oracle 把 CPU 和 PSU 合并发布了,也就是说PSU 本身已经包含了当季的安全补丁内容,不需要另外再打一个 CPU。你只需要确认补丁号对应的季度即可。P33477185 里面实际上包含多个子补丁:
- 数据库 PSU 本体(Database PSU 11.2.0.4.220118)
- OJVM 组件补丁(如果属于 Stack Patch 合并发布,会一并打包)
- 可能附带的客户端/网关补丁
不过在 11.2.0.4 的后期 PSU 里,OJVM 通常会单独发布。所以你解压后看到的33477185主目录下,很可能还有一个类似p33477185_112040_Linux-x86-64.zip的文件,先解压看结构。
另外,这个 PSU 针对的是数据库软件本身,不包括 Grid Infrastructure。如果环境是 RAC 或者装了独立 ASM,还需要额外关注 GI 的补丁。很多新手在这里栽过跟头:以为打了 DB PSU,GI 就一起升了,实际上GI 补丁需要单独下载、单独应用。所以拿到 P33477185 之前,先明确你的架构是什么。如果是 RAC + ASM,得把 GI PSU 一起准备好。如果是单机文件系统,那打这一个就够了。
2. 动手前的关键检查:这三项没做,后面全是坑
2.1 确认当前补丁基线
在打任何 PSU 之前,第一步永远是检查现状。登录服务器后,先做三件事:查 Oracle 版本、查 OPatch 版本、查当前已安装的补丁清单。
用 SQL*Plus 确认数据库版本,这一步的目的是核对当前版本是否处于 11.2.0.4 的基础版本(Base Release)还是已经应用过较旧的 PSU。
SQL> SELECT * FROM v$version;如果之前已经打过低版本的 PSU,比如 11.2.0.4.201020(2020 年 10 月之前的 PSU),此时需要关注的是PSU 之间的覆盖关系和冲突。Oracle 的 PSU 是累积的,新 PSU 包含旧 PSU 的所有修复,但应用新 PSU 时不必非得先卸载旧的,OPatch 会处理覆盖逻辑。不过有一个例外:如果环境里安装了针对某个 bug 的个别 Patch(One-off Patch),而这些 patch 和 PSU 的修复文件有交集,可能产生冲突,这时需要查 MOS 文档确认是否需要先回滚对应补丁。
第二步,查 OPatch 版本。
$ORACLE_HOME/OPatch/opatch versionOPatch 工具的版本要求可以直接看官方文档号 2339920.1,里面有每个季度 PSU 对 OPatch 的最低版本要求。比如 2022 年 1 月的 PSU 要求 OPatch 11.2.0.3.36 以上。很多人在这一步翻车,OPatch 版本太老导致 apply 直接报错,而且报错信息未必直说版本低,可能是一些莫名其妙的 XML 解析错误或OPatch failed。
第三步,查看已安装补丁。
$ORACLE_HOME/OPatch/opatch lsinventory重点关注列表里是否有OJVM PSU、CPU、BUNDLE PATCH这些同类补丁。如果有,需要确认新补丁是否可以叠加,否则会收到conflict exists的错误提示。这个错误其实是好事,总比打了一半挂掉强。遇到冲突先别慌,读一下 OPatch 输出的冲突详情,通常它会明确告诉你冲突的补丁号和冲突文件,据此判断是回滚旧补丁还是调整方案。
2.2 备份的粒度决定了你能不能后悔
打补丁前必须做备份,但备份的方式要分情况。对于数据库软件本身,不需要备数据文件,但必须备 $ORACLE_HOME。最简单的做法是 tar 打包:
tar -czf /backup/ora_home_$(date +%Y%m%d).tar.gz $ORACLE_HOME这里有个细节,如果是 RAC 环境,每个节点都要打,每个节点的 $ORACLE_HOME 都要备份,不要只备份一个节点就以为完事了。因为补丁应用过程实际上是替换二进制文件,每个节点的软件目录是独立的。
数据库层面的备份,这个看环境和风险承受能力。核心生产库建议至少做一次控制文件备份和归档日志备份,用 RMAN 的话一条命令就行:
RMAN> backup current controlfile format '/backup/ctl_%U.bak';实际上,打 PSU 本身不会动数据文件,99% 的情况下数据是安全的。但 DBA 这个岗位不能赌那 1% 的可能性,出过一次事就得背处分,所以该备的还是要备。尤其是数据库里如果跑着大量存储过程、函数、视图,打补丁后虽然理论上对象不受影响,但代码失效后重新编译需要的时间远超预期,这也是为什么后面我会专门讲编译无效对象。
2.3 停止服务和清理环境
在正式 apply 之前,需要停掉数据库实例和监听。注意顺序:先停监听,再停实例。如果搞反了,实例停机过程中监听从 PMON 获取不到注册信息,客户端连接会报 ORA-12514 之类的错误,印象不好但不算致命。规范操作是:
lsnrctl stop sqlplus / as sysdba SQL> shutdown immediate;这里为什么停监听?不是因为它影响补丁安装,而是防止在补丁安装期间有新的连接进来。虽然补丁安装是在软件目录层面替换文件,运行中的实例如果加载了旧版本共享库,可能导致会话行为不一致,甚至在某些特殊场景下触发 core dump。保险起见,干净利落地停掉所有数据库进程。
如果是 RAC,需要把该节点的实例和监听都停止:
srvctl stop instance -d <dbname> -i <instance_name> srvctl stop listener -n <nodename>这里还要提一个很隐蔽的问题:环境变量里的 ORACLE_HOME 可能指向旧路径。比如之前从 11.2.0.3 升级到 11.2.0.4,但用户的 .bash_profile 里写的还是旧路径。补丁装在 11.2.0.4 的 $ORACLE_HOME 下,而 SQL*Plus 却调用的旧版本,指令完全乱了。所以打补丁前,务必要核对当前会话里的路径是不是目标 ORACLE_HOME:
echo $ORACLE_HOME which sqlplus这一步看着简单,但生产环境里因为环境变量没配对导致打了半天发现打错目录的案例不在少数。
3. 应用 PSU 的三个阶段:解压、OPatch、SQL 脚本
3.1 解压和准备工作
先将 ZIP 包放到一个空间充足、有执行权限的目录下。注意,不建议放在 /tmp 下,因为有些系统 /tmp 是 noexec 挂载的,直接导致后续的命令无法执行。放在/u01/software或/home/oracle/patch这类专门目录比较稳。
unzip p33477185_112040_Linux-x86-64.zip解压后会出现一个以补丁号命名的目录,比如33477185。进入这个目录,里面通常有这些文件:
etc/目录:存放补丁属性文件files/目录:真正要被替换的二进制文件README.txt:官方说明文档patchmd.xml:补丁元数据
在 apply 之前,建议先花五分钟读一下 README 里面的“Pre-Installation Instructions”部分,特别是确认是否有额外的操作要求。比如某些 PSU 需要先执行某个 SQL 脚本来刷新数据字典,或者需要设置某个隐藏参数。P33477185 这个补丁相对常规,一般没有特殊要求。
还有一步是在 apply 前更新 OPatch。如果第 2 节检查时发现 OPatch 版本过低,需要先从 My Oracle Support 下载新版的 OPatch,按官方说明解压覆盖到$ORACLE_HOME/OPatch目录下。更新前记得备份旧版本:
mv $ORACLE_HOME/OPatch $ORACLE_HOME/OPatch_bak_$(date +%Y%m%d) unzip -o p6880880_112000_Linux-x86-64.zip -d $ORACLE_HOME最后一步也别忘了检查补丁目录的文件属主。必须用 oracle 用户来执行,或者是拥有 $ORACLE_HOME 写权限的用户。用 root 或别的用户操作容易带着权限问题跑排查。提前用chown -R oracle:oinstall 33477185保证目录归属正确。
3.2 执行 opatch apply 的正确姿势
进入到补丁目录后,执行:
$ORACLE_HOME/OPatch/opatch apply这里我强烈建议加-invPtrLoc参数指定 oraInst.loc 文件位置,尤其是在多实例环境或者 GI 与 DB 装在不同层级的情况下。不指定的话,OPatch 会自己去搜 oraInventory,搜错了位置就会报Cannot find Central Inventory或没有权限的错:
$ORACLE_HOME/OPatch/opatch apply -invPtrLoc /etc/oraInst.loc虽然很多单机环境不加这个参数也没问题,但加了更稳,不会因为或Inventory目录找不到而中断。
在执行过程中,OPatch 会先做前置检查,包括空间检查、依赖检查、冲突检查。这一阶段会输出大量日志,如果日志没有任何报错但进程很长时间没动静,别急着 Ctrl+C。补丁应用过程中有些步骤确实耗时较长,比如日志里出现Updating archive files...的时候,是在替换 jar 包和共享库,最长的能跑十几分钟。你得有点耐心,多观察一下再判断是不是真的卡住了。
等执行完,OPatch 会提示:
OPatch succeeded.这句输出是判断成功的重要标志。如果出现OPatch failed,就要仔细看日志。失败的常见场景:
- 权限不足:目录或文件属主不对
- 空间不足:$ORACLE_HOME 所在分区剩余空间不够
- 进程占用:某些进程还在运行,导致文件无法替换
针对占用进程的情况,可以用fuser命令查看是哪个进程在占文件:
fuser -v $ORACLE_HOME/lib/libserver11.a如果发现某个进程确实还占着,就去杀掉,或在 RAC 环境下确认 srvctl 停干净了。
3.3 跑 SQL 脚本:这一步才是补丁真正生效的关键
OPatch apply 只是替换了二进制文件,数据字典的更新要靠 SQL 脚本来完成。这一步漏掉或者失败,补丁等于白打,而且后续可能出现版本状态不一致的问题。
先启动数据库到 upgrade 模式(11.2.0.4 通常建议直接startup upgrade,这是最安全的方式):
sqlplus / as sysdba SQL> startup upgrade然后在 SQL*Plus 里执行补丁目录下的脚本。根据 README 的说明,不同补丁的脚本路径可能不同。P33477185 这类 PSU 一般是在$ORACLE_HOME/rdbms/admin下执行catupgrd.sql:
SQL> @$ORACLE_HOME/rdbms/admin/catupgrd.sql这个脚本执行时间与数据字典大小相关,小库可能几分钟就完,大库有可能需要半小时以上。期间会输出大量日志,最后通常能看到类似catupgrd.sql completed的提示。
脚本执行完后,不能马上打开数据库。先关闭再重启到正常模式:
SQL> shutdown immediate; SQL> startup;启动之后再跑一遍utlrp.sql来重新编译无效对象:
SQL> @$ORACLE_HOME/rdbms/admin/utlrp.sql这里解释一下为什么要做这一步:补丁更新了数据字典视图定义和内部包,原本依赖旧字典对象的 PL/SQL 可能被标记为 INVALID。utlrp.sql会扫描所有 INVALID 对象并尝试逐个重新编译。它通常是多遍执行的,只要还有无效对象就继续编译,直到没有可修复的对象为止。
优化建议是:别急着在 utlrp.sql 跑完前开业务。有些 DBA 图省事,utlrp.sql 跑到一半就开库放业务进来了,结果业务 SQL 执行时报 ORA-04068 之类的错误,用户直接投诉到领导那。等几分钟让编译跑完,绝对值得。
如果是 RAC 环境,SQL 脚本只需要在一个节点上执行,不需要所有节点都跑。但补丁二进制每个节点都要 apply。
4. 安装后验证:五大检查项,少一个都别认为成功
看到opatch succeeded和catupgrd.sql completed后,还得做一轮全面验证。我一般按下面这五步走,每一步都有实际意义。
4.1 lsinventory 确认补丁在册
$ORACLE_HOME/OPatch/opatch lsinventory输出里应该能看到33477185和状态为APPLIED。同时确认补丁名中包含(Jan 2022)或220118的字样。
如果这里看到INVALID或APPLIED却没有正确的补丁标识,说明可能打错了补丁或者 OPatch Inventory 损坏。后者比较麻烦,需要恢复旧 OPatch 或重建 inventory,这个属于应急排障的范畴,建议先查看$ORACLE_HOME/cfgtoollogs/opatch/目录里的日志,多数情况下能定位到原因。
4.2 数据字典版本核对
登录数据库,查询数据字典的版本信息:
SQL> SELECT version, status FROM v$instance; SQL> SELECT comp_id, version, status FROM dba_registry;正常情况下,各组件版本应该更新到 11.2.0.4.220118 左右,状态为VALID。如果某个组件状态为UPGRADED或INVALID,说明该组件对应的升级脚本没跑完,需要针对性处理,比如手动执行对应的组件脚本。
值得单独提醒的是Oracle Database Catalog Views和Oracle Database Packages and Types这两行的状态,它们是最容易在补丁后出现异常的。如果这两个组件的版本比其他组件低,大概率是catupgrd.sql跑到一半没执行完整。
4.3 无效对象清零检查
SQL> SELECT owner, object_type, count(*) FROM dba_objects WHERE status = 'INVALID' GROUP BY owner, object_type;这条查询是判断补丁后健康度的“体温计”。正常情况下SYS、SYSTEM下不应该有大量失效对象,业务模式下的少量 INVALID 可能是历史遗留,但如果是系统对象大面积 INVALID,说明utlrp.sql没跑好或跑得太早。
如果查询结果不为空,可以重跑一遍utlrp.sql:
SQL> @$ORACLE_HOME/rdbms/admin/utlrp.sql再查一次。正常情况下第二次跑完就应该清零或只剩极少的历史对象。如果还有大量失效对象,那就要看具体是哪些对象因为什么原因失效,常见的包括ORA-04021 timeout occurred while waiting to lock object(并发锁导致编译等待)和ORA-04045 errors during recompilation(依赖对象被锁或缺失)。
4.4 监听和实例服务注册
打完补丁后,监听可能由于之前被 stop 还没启动,需要手动拉起:
lsnrctl start lsnrctl status在 SQL*Plus 里确认服务注册正常:
SQL> show parameter local_listener; SQL> show parameter service_names;然后通过监听状态确认数据库实例已注册到监听上:
lsnrctl services这一步在 RAC 环境下尤其重要,因为补丁应用后节点可能没有自动恢复服务注册。如果lsnrctl services看不到目标服务名,RAC 就会面临连不上的问题。处理方法是重启监听:
srvctl stop listener -n <nodename> srvctl start listener -n <nodename>多数情况下重启监听就能把服务重新注册上来。
4.5 关键功能冒烟测试
这部分直接关系到业务能否恢复。根据系统的核心功能,做一轮冒烟测试。比如典型的:
- 能正常连接数据库:
sqlplus system@orcl - 能正常执行增删改查:通过业务账号执行核心表的 DML
- 能正常跑定时任务:确认 DBMS_SCHEDULER 任务调度正常
- 能正常操作 ASM(若适用):
asmcmd ls能列出磁盘组内容
冒烟测试的粒度取决于业务要求。数据库层面的核心能力验证通过后,再开放业务接入。不建议在补丁后让整个业务体系一次性接入,而是先让部分应用连上库跑几分钟,确认无异常再全量放开。
5. 回滚方案:只有遇到无解问题时才走这条路
补丁不是总能一次成功。当系统上线后出现严重异常且修复成本远大于回滚成本时,就需要回滚。回滚同样分两步:先回滚补丁二进制,再回滚数据字典。
5.1 二进制回滚
前提是 OPatch Inventory 中还有回滚所需的备份信息。执行:
$ORACLE_HOME/OPatch/opatch rollback -id 33477185这个过程就是把打补丁前保存的旧版本文件还原回来。如果补丁应用过程中某些文件已经被新版本占用导致回滚失败,就得靠预处理时备份的$ORACLE_HOMEtar 包来手动还原整个目录。这也是为什么前面反复强调备份的重要性,没有完整备份,回滚根本无从谈起。
5.2 数据字典回滚
二进制回滚完成后,还要把数据字典回到之前的状态。这里有个普遍存在的误解:PSU 的 SQL 升级通常不支持降级(Downgrade),也就是说catupgrd.sql跑过之后,很难通过官方脚本把数据字典降回旧版本。唯一的可靠方案是从备份恢复数据库。
所以,如果你判断补丁造成的问题无法通过后续修复解决、必须回滚时,步骤是:
- 对当前数据库做一次全备或至少备份控制文件(作为最后保险)
shutdown immediateopatch rollback -id 33477185- 用补丁前的 RMAN 备份恢复数据库
- 启动数据库并做完整性验证
这里要泼盆冷水:别轻易回滚。补丁后的异常很多时候不是补丁本身引起的,而是验证不到位、对象没编译完整、参数配置不对。我见过一个案例,打完补丁后业务报 ORA-00942(表或视图不存在),客户着急回滚,后来排查发现是应用账号连到了另一个 PDB 或另一套库,跟补丁一点关系没有。所以先冷静排查,确认是补丁本身的问题再考虑回滚。
6. 命中率最高的几个“异常现场”和应对思路
6.1 “ORA-00980 同义词转换不再有效”或大量 Package 失效
这个问题常见于补丁后第一次执行应用 SQL 时。根源多半是数据字典升级过程中,应用账号下的私有同义词或视图依赖的对象被重建过,而旧版本的 PL/SQL 缓存还在内存中。处理方式很直接:重启实例,把缓存清掉,再执行业务 SQL。如果是持久性失效,检查dba_objects里 INVALID 的对象,用DBMS_UTILITY.COMPILE_SCHEMA或utlrp.sql再次编译。
6.2 OPatch apply 时报 “Patch 33477185 is not applied in the Oracle Home”
这个报错通常不是真的没打上,而是ORACLE_HOME与opatch在读取 Inventory 时路径不一致。确认当前会话的ORACLE_HOME和ORACLE_BASE是否正确,并检查/etc/oraInst.loc指向的 inventory 目录是否属于当前ORACLE_HOME。很多时候把环境变量修正后重新执行opatch lsinventory就能正常识别。
6.3opatch apply执行到一半卡住,日志出现Archive file is busy
说明该文件被某个进程锁住,最常见的用户进程是ora_pmon、ora_dbw0等实例进程。确认你已经shutdown了实例,如果确实关了还有进程占用,可以用ps -ef | grep ora_查一遍看是否有残留进程。RAC 环境下某个节点没彻底停干净也会导致跨节点的 NFS 共享目录文件被锁住。
6.4 补丁后sqlplus版本还是旧版本
这是因为sqlplus命令的 PATH 里优先找到了别处的可执行文件。运行which sqlplus确认路径,如果不是$ORACLE_HOME/bin/sqlplus,则需要调整 PATH 环境变量,或者绝对路径调用即可。
7. 针对 11.2.0.4 生命周期的一点建议
这里想多说几句关于版本选择的判断。11.2.0.4 早在 2020 年就结束了 Premier Support,目前处于 Extended Support 阶段。如果你所在的环境还允许升级到更高版本,比如 19c,我建议尽量安排升级。因为即使是 PSU 类型的补丁,在 11.2.0.4 上修复已知 bug 的响应速度也越来越慢,Oracle 不会在这个老版本上投入太多新功能开发。
但现实是很多系统由于业务兼容性、硬件配置、项目预算等原因,短期内无法升级。这种情况下,按季度定期应用 PSU 是最有效的风险控制手段。同时需要做的是:
- 密切跟踪 MOS 上针对 11.2.0.4 的关键已知问题
- 保留一份可靠的备库或至少保证 RMAN 备份的有效性
- 新环境安装时直接采用当前最新的 PSU 补丁集,而不是装完 Base Release 再用旧补丁叠加
关于 P33477185 这个补丁本身,需要说明的是,它只适用于正式发布的 11.2.0.4.0。如果你的数据库版本是 11.2.0.3 或更低,需要先升级到 11.2.0.4 的基础版本再打这个补丁,不能跨版本直接应用。这条在 README 开头也有明确提示。
最后再分享一个细节:补丁目录里的 README 一定不要跳过。我知道大家看到英文文档就头大,但 README 中会明确写清楚该补丁的适用范围、注意事项和已知问题,这些信息在 My Oracle Support 上都有对应说明,提前扫一眼能在实施中减少很多不必要的猜测。我每次打补丁前都会把 README 的 Pre-Install 和 Post-Install 两段各读一遍,养成了习惯之后,实施成功率确实比之前凭经验硬干高了不少。
本文还有配套的精品资源,点击获取