ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Oracle 11.2.0.4 PSU补丁安装与回退实战指南

Oracle 11.2.0.4 PSU补丁安装与回退实战指南

简介:该资源为 Oracle 数据库 11.2.0.4 版本的 PSU 补丁包,补丁编号 p33477185,发布于 2022 年 1 月,面向需要为 Linux x86-64 平台数据库打补丁的 DBA 与运维人员,用于修复安全漏洞、优化性能并解决已知问题。压缩包共 3658 个文件,约 436.52MB,以 so 动态库、o 目标文件、xml 元数据、sql 脚本及 plb、class、jar 等为主,涵盖补丁程序、安装说明与依赖组件,结构完整。目前已有 859 人学习下载。包内 PatchSearch.xml 提供补丁元数据与适用条件,33477185 对应实际安装文件,可配合 OPatch 完成解压、应用与验证;借助这些内容,读者能核对版本兼容性、按规范备份并部署补丁,同时参考后置步骤与监控建议,降低升级风险,适合作为 11g 数据库补丁管理的实操参考。

1. 从一次 PSU 补丁翻车说起:DB-PSU-11.2.0.4.220118 到底装的是什么

去年冬天,某实验室一台跑了三年多的 Oracle 11.2.0.4 测试库突然在凌晨批量任务里报出 ORA-00600,trace 文件里指向一个优化器相关的内部错误。查了一圈,最终定位到是某个已知 bug,而修复它的正是 2022 年 1 月发布的 PSU 补丁——DB-PSU-11.2.0.4.220118,补丁号 p33477185,平台 Linux x86-64。当时我以为打个补丁就是opatch apply一条命令的事,结果因为 OPatch 版本太老、/tmp空间不够、以及漏跑了 datapatch,前后折腾了整整一个下午。这套环境在政企、金融、制造业的内网里极其常见,11.2.0.4 虽然早已不是主流版本,但存量系统太多,PSU 补丁的安装和回退依然是运维绕不开的基本功。这篇笔记写给正在给 11.2.0.4 打 PSU 的同行,尤其是第一次独立操作、怕把库搞坏的新手——我会把版本选择、前置检查、安装步骤、datapatch 执行和回退方案一步步拆开,照着走能跑通,出了问题也知道去哪儿救。

2. 装前把环境列清楚:版本、OPatch 与空间的三重校验

2.1 确认数据库版本和已装补丁清单

动手之前,先把当前库的底细摸清楚。很多人上来就解压补丁包,结果发现 OPatch 版本不满足补丁要求,或者当前已经装过更新的 PSU,白忙一场。第一步永远是查版本和补丁列表。

# 切换到 oracle 用户,确认数据库版本 $ORACLE_HOME/bin/sqlplus -v # 查看当前已安装的补丁清单,重点看有没有比 220118 更新的 PSU $ORACLE_HOME/OPatch/opatch lspatches # 查看 OPatch 自身版本,11.2.0.4 打 2022 年补丁一般要求 11.2.0.3.20 以上 $ORACLE_HOME/OPatch/opatch version

sqlplus -v输出里要确认是11.2.0.4.0这个基线版本,PSU 是叠加在基线之上的。opatch lspatches会列出所有已应用的补丁号,如果里面已经出现了比 p33477185 更新的补丁,就别再往下走了,否则可能触发补丁冲突。opatch version这一条最容易被忽略——2022 年的 PSU 通常要求 OPatch 至少是 11.2.0.3.20,低于这个版本opatch apply会直接报错退出。我一般会先把 OPatch 升级到对应版本再动 PSU,升级方法在 2.3 节说。

2.2 检查磁盘空间和临时目录

补丁解压和安装过程对空间有硬性要求,尤其是/tmp。11.2.0.4 的 PSU 解压后大概几百 MB,但 OPatch 在 apply 阶段会往/tmp写大量临时文件,空间不够会在中途报No space left on device,而且这时候补丁可能已经改了一半,回退起来很麻烦。

# 检查 ORACLE_HOME 所在分区剩余空间,建议至少留 5G df -h $ORACLE_HOME # 检查 /tmp 空间,建议至少 2G,不够就临时扩或改 TMP 环境变量 df -h /tmp # 如果 /tmp 确实紧张,可以指定其他目录作为 OPatch 临时区 export TMP=/u01/app/tmp export TMPDIR=/u01/app/tmp

df -h看的是挂载点剩余空间,不是目录本身大小。TMP和TMPDIR这两个环境变量要在执行opatch apply的同一个 shell 里 export,否则不生效。我一般会在/u01/app下建一个tmp目录专门给 OPatch 用,避免和系统/tmp抢空间。这一步做完,环境层面的坑基本排掉了。

2.3 升级 OPatch 到匹配版本

如果 2.1 里查到 OPatch 版本偏低,先升级它。OPatch 本身也是一个补丁包,解压后覆盖原目录即可,但要注意备份。

# 备份现有 OPatch,出问题可以回滚 mv $ORACLE_HOME/OPatch $ORACLE_HOME/OPatch_bak # 解压新版 OPatch 到 ORACLE_HOME unzip -q p6880880_112000_Linux-x86-64.zip -d $ORACLE_HOME # 确认版本已更新 $ORACLE_HOME/OPatch/opatch version

mv那一步是后悔药,别省。解压完成后 OPatch 目录权限可能变成当前用户,需要确认属主是 oracle:oinstall,否则后续 apply 会报权限错误。opatch version输出正常就说明升级到位了。这里有个细节:OPatch 升级不需要停库,但 PSU 安装需要,所以顺序是先升 OPatch,再停库,再打 PSU。

3. 正式安装 PSU:从解压到 opatch apply 的完整链路

3.1 停库与解压补丁包

PSU 安装要求数据库实例和监听都停掉,但不需要停 ASM(如果有独立 ASM 实例的话,ASM 可以不停)。停库顺序是先停监听再停实例,或者反过来都行,关键是确认进程真的退干净了。

# 停监听 $ORACLE_HOME/bin/lsnrctl stop # 停实例,注意用 sysdba 登录 $ORACLE_HOME/bin/sqlplus / as sysdba <<EOF shutdown immediate; exit; EOF # 确认没有残留的 oracle 进程 ps -ef | grep pmon | grep -v grep

shutdown immediate比shutdown abort安全,除非实例已经 hang 住,否则别用 abort。ps -ef | grep pmon这条是确认实例真的停了,有时候 shutdown 卡住但命令返回了,pmon 还在,这时候打补丁会出问题。停库之后解压 PSU 包:

# 解压 PSU 到独立目录,不要解到 ORACLE_HOME 里 mkdir -p /u01/soft/psu220118 cd /u01/soft/psu220118 unzip -q p33477185_112040_Linux-x86-64.zip # 查看解压后的目录结构,确认补丁号 ls -l

解压出来的目录名通常就是补丁号,里面有一个README.html和补丁子目录。我一般会先扫一眼 README 里的 Prerequisites 部分,确认没有额外的前置补丁要求。这一步花两分钟,能省掉后面报错再回头查的时间。

3.2 用 opatch prereq 做安装前检查

opatch apply之前,强烈建议先跑opatch prereq,它会检查补丁能不能装、有没有冲突、OPatch 版本够不够。这个命令不修改任何东西,纯检查。

cd /u01/soft/psu220118/33477185 # 检查补丁适用性,-phBaseDir 指向补丁解压目录 $ORACLE_HOME/OPatch/opatch prereq CheckApplicable -phBaseDir /u01/soft/psu220118/33477185 # 检查补丁冲突 $ORACLE_HOME/OPatch/opatch prereq CheckConflictAgainstOHWithDetail -phBaseDir /u01/soft/psu220118/33477185

CheckApplicable会输出补丁是否适用于当前 ORACLE_HOME,如果报Not applicable,多半是版本不对或者已经装过。CheckConflictAgainstOHWithDetail检查冲突,如果报出某个已装补丁和当前 PSU 冲突,需要先确认哪个更新,通常保留更新的那个。这两条命令的输出要仔细看,不要只看最后一行Prereq结果,中间的WARNING也要读。

3.3 执行 opatch apply 并观察输出

检查通过后,正式 apply。这一步会修改 ORACLE_HOME 下的二进制文件和库文件,过程中不要中断,不要开第二个窗口做别的操作。

cd /u01/soft/psu220118/33477185 # 执行补丁安装,-silent 减少交互,日志同时输出到屏幕和文件 $ORACLE_HOME/OPatch/opatch apply -silent 2>&1 | tee /u01/soft/psu220118/apply.log

-silent会跳过确认提示,适合脚本化操作,但第一次装建议不加-silent,看清楚每一步提示再回车。tee把输出同时写到日志文件,出问题可以回溯。apply 过程中会看到Applying patch和Patching component之类的输出,最后出现OPatch succeeded才算成功。如果中途报错,日志里会指明是哪个文件或哪个检查失败,根据报错去查,不要盲目重跑。

3.4 启动实例并执行 datapatch

apply 成功只是把二进制补丁装上了,数据库里的数据字典还没更新,必须启动实例后跑 datapatch。这一步是 11.2.0.4 打 PSU 最容易漏掉的环节,漏了会导致数据库行为不一致,甚至起不来。

# 启动实例到 mount 或 open 状态 $ORACLE_HOME/bin/sqlplus / as sysdba <<EOF startup; exit; EOF # 执行 datapatch,它会读取补丁里的 SQL 并应用到数据库 cd $ORACLE_HOME/OPatch ./datapatch -verbose

startup之后数据库应该是 open 状态,如果起不来,先看 alert log。datapatch -verbose会输出每个 SQL 的执行情况,最后显示Patch installation complete或类似信息。如果 datapatch 报错,常见原因是实例没起全、或者之前有失败的 datapatch 残留,需要先datapatch -rollback清理再重跑。跑完 datapatch,整个 PSU 安装才算真正完成。

4. 避坑与排查:五个让我加班到深夜的 PSU 安装问题

4.1 OPatch 版本过低导致 apply 直接失败

现象:执行opatch apply后立刻报错,提示OPatch version 11.2.0.3.x is lower than the minimum required version,补丁根本没开始装。

原因:11.2.0.4 自带的 OPatch 版本往往停留在 11.2.0.3.12 左右,而 2022 年的 PSU 要求至少 11.2.0.3.20。版本不匹配时 OPatch 会拒绝执行,这是保护机制,不是 bug。

解决:按 2.3 节的步骤先升级 OPatch,升级完再跑opatch version确认。升级 OPatch 不需要停库,但升级后要重新执行opatch prereq检查,因为新 OPatch 的检查逻辑可能和老版本不同。

4.2 /tmp 空间不足导致 apply 中途失败

现象:opatch apply跑到一半报No space left on device,补丁状态变成PARTIAL,数据库起不来。

原因:OPatch 在 apply 阶段会把补丁文件复制到/tmp下做临时处理,如果/tmp是独立分区且空间小于 2G,很容易撑爆。撑爆之后补丁只应用了一部分,ORACLE_HOME 处于不一致状态。

解决:先按 2.2 节的方法把TMP和TMPDIR指向空间充足的目录,然后执行opatch rollback -id 33477185回退已应用的部分,再重新 apply。如果 rollback 也失败,就需要从备份恢复 ORACLE_HOME,所以打补丁前对 ORACLE_HOME 做一次冷备是值得的。

4.3 漏跑 datapatch 导致数据库行为异常

现象:apply 成功,实例也能启动,但某些 SQL 执行计划突变,或者报出ORA-04061之类的错误,查 alert log 没有明显异常。

原因:PSU 包含两部分,二进制补丁和 SQL 补丁。opatch apply只装了二进制部分,SQL 部分要靠datapatch写入数据字典。漏跑 datapatch 时,二进制和字典不一致,就会出现各种玄学问题。

解决:启动实例后立即执行datapatch -verbose,确认输出里有Patch installation complete。如果已经漏跑了一段时间,补跑 datapatch 即可,不需要重新 apply。补跑前建议先做一次全库备份,因为 datapatch 会修改数据字典。

4.4 补丁冲突导致 prereq 检查不通过

现象:opatch prereq CheckConflictAgainstOHWithDetail报出某个已装补丁和当前 PSU 冲突,提示Conflict with patch xxxxxxxx。

原因:当前 ORACLE_HOME 里已经装了一个和 p33477185 修改了相同文件的补丁,两个补丁不能共存。常见于之前打过其他 PSU 或一次性补丁。

解决:先确认哪个补丁更新。如果已装的补丁比 p33477185 新,就不需要再装这个 PSU;如果已装的更旧,需要先opatch rollback回退旧补丁,再装新的。回退前务必确认旧补丁没有其他依赖,回退后数据库可能需要重新跑 datapatch。

4.5 回退时忘记回退 datapatch

现象:执行opatch rollback -id 33477185成功,但数据库启动后报错,或者行为仍然像装了补丁。

原因:rollback 只回退了二进制部分,datapatch 写入的 SQL 变更还在数据字典里。二进制回退后字典和二进制又不一致了。

解决:rollback 之后,启动实例到 open 状态,执行datapatch -rollback回退 SQL 部分。顺序是先用 opatch rollback 回退二进制,再用 datapatch -rollback 回退 SQL,两步都完成才算真正回退。回退完成后建议重启一次实例,确认 alert log 没有异常。

5. 装完怎么验证:三条命令确认 PSU 真正生效

补丁装完不是看到OPatch succeeded就结束了,得验证二进制和字典两边都到位。我一般用三条命令交叉确认,少一条都不放心。

第一条,查 opatch 补丁列表,确认 p33477185 在列:

$ORACLE_HOME/OPatch/opatch lspatches | grep 33477185

输出里应该能看到33477185和对应的描述信息。如果 grep 不到,说明二进制补丁没装上,回头查 apply 日志。

第二条,查数据库注册的补丁信息,确认 datapatch 生效:

-- 以 sysdba 登录后执行 SELECT patch_id, patch_type, action, status, action_time FROM dba_registry_sqlpatch ORDER BY action_time DESC;

dba_registry_sqlpatch是 11.2.0.4 之后才有的视图,里面记录了每次 datapatch 的操作。status列应该是SUCCESS,action是APPLY。如果这个视图查不到记录,说明 datapatch 没跑或者没跑成功。

第三条,查组件版本,确认 ORACLE_HOME 里的组件版本号有变化:

SELECT comp_id, version, status FROM dba_registry WHERE comp_id IN ('CATALOG','CATPROC');

CATPROC的 version 应该和 PSU 的版本对应,status 是VALID。如果 status 是INVALID,需要跑utlrp.sql重新编译无效对象。

三条都对上,才算真正装完。从那以后我每次打完 PSU,都会把这三条命令走一遍,再顺手看一眼 alert log 末尾有没有 ORA- 错误。补丁这东西,装的时候小心,验的时候较真,后面才能睡得踏实。希望帮到你。

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

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进