简介面向 Oracle Database 11.2.0.3 的补丁集更新包编号 20760997集成 2015 年 7 月关键补丁更新CPU适用于 Linux x86-64 平台。补丁集更新涵盖安全修复、稳定性改进与性能优化可降低已知漏洞攻击风险尤其适合仍运行该版本的数据库实例。压缩包约 100.73MB内含补丁程序及配套配置说明便于在维护窗口内完成备份、停库、部署与验证。已有 290 人学习下载一次性应用可聚合多项修复减少多次打补丁带来的停机时间并强化数据库安全。安装前需检查兼容性并准备回滚方案是保障生产环境安全与业务连续性的实用运维工具。1. Oracle补丁包拿到手先读懂文件名再动手标题是p20760997_112030_Linux-x86-64.zip这样一个典型Oracle patch很多人第一反应是解压、看README、直接跑opatch apply实际上最容易翻车的恰恰是跳过文件名解析。Oracle补丁的命名有一套固定编码p后面的数字是补丁号112030代表主版本11.2.0.3.0Linux-x86-64是目标平台三者组合起来才能确认这份资源是否落在你的环境里。下面用一个老DBA的拆包流程讲清楚补丁类型识别、OPatch准备、应用与回滚、验证这几个环节里真正值得动手和值得记笔记的地方。适合手里握着Oracle 11g环境、准备做季度补丁更新的运维或DBA。2. 补丁定位与安装前置先分清五种补丁类型再检查OPatch2.1 补丁类型决定了流程差异别把季更当成小补丁打拿到命名格式像p20760997_112030_Linux-x86-64.zip的文件先不要急着解压。常见的Oracle补丁至少能分出五类类型不同安装前置条件和后续动作完全不同。补丁类型常见命名特征适用场景是否需要数据库重启季度更新补丁号随机README中写明是季度更新定期做版本基线同步一般需要一次性补丁p8位数字README标注interim patch修复特定Bug按README要求Patch Set命名中带完整版本号如11.2.0.4跨版本升级必须关键补丁更新CPU日期通常与安全相关安全合规要求必须OPatch工具包固定补丁号p6880880升级OPatch工具本身不需要重启数据库判断依据不要只看文件名解压后先打开README文件头几行会写明补丁类型、对应数据库版本和支持的操作系统。我一般会先做这个动作因为同类后缀的zip在支持门户里有时存在多个变体仅凭文件名容易拿错。若是季度更新那后续的post-install阶段可能涉及数据字典视图的更新脚本这一点后面专门讲。这里最容易踩的认知偏差是把一次性补丁当季更来打。一次性补丁往往只覆盖少量文件安装时间以分钟计而季更补丁通常涉及大量二进制重链和目录权限调整安装时间以小时计。如果按一次性补丁的预期去安排停库窗口中途发现时间不够就只能选择回滚风险反而被放大了。反过来把季更当一次性补丁打OPatch会在冲突检测阶段直接拒绝报错信息类似interim patch 已安装在系统上这时候还得先处理旧补丁平白多一次来回。2.2 检查OPatch工具版本这是最容易忽略的前置检查项OPatch是Oracle补丁应用工具它和数据库软件本身是独立安装的存在于ORACLE_HOME/OPatch目录下。不同补丁对OPatch有最低版本要求README里通常会写明OPatch version must be greater than ...。cd $ORACLE_HOME/OPatch ./opatch version这个命令输出的第一行就是当前OPatch版本。如果版本低于补丁包要求按顺序先升级OPatch工具常用补丁号p6880880下载对应平台版本后直接解压覆盖到$ORACLE_HOME/OPatch目录。mv $ORACLE_HOME/OPatch $ORACLE_HOME/OPatch_bak_$(date %Y%m%d) unzip /patch_src/p6880880_112000_Linux-x86-64.zip -d $ORACLE_HOME chown -R oracle:oinstall $ORACLE_HOME/OPatch $ORACLE_HOME/OPatch/opatch version这里有一个常见误区有人把OPatch升级放在应用补丁之后结果opatch apply中途报错报错信息是OPatch version check failed。这个错误不影响数据库但是整个会话被中止得重新走一次apply。所以我的习惯是任何补丁包落地前先执行一遍opatch version并把版本号记录在案。升级时备份旧OPatch目录是给自己留后悔药避免新版本工具与旧补丁记录格式不兼容时无法回退。2.3 README阅读清单动手前先画三行笔记README不只说明补丁类型还包含三个关键信息前置补丁、冲突列表和命令样例。前置补丁解决的是依赖问题冲突列表解决的是已打补丁之间的交叉影响命令样例则告诉你该调用的opatch子命令和参数。我一般把这三项抄在一张纸上或者记在文本文件里装完对照打勾。特别是前置补丁如果在同一台环境里已经打过一个同系列补丁再次应用后续补丁时大概率会遇到conflictREADME中会有说明应该使用opatch apply还是opatch napply。这一点在第4章会展开。README里的命令样例常写成带绝对路径的形式例如/u01/app/oracle/product/11.2.0/dbhome_1/OPatch/opatch apply直接复制执行没问题。但如果没有设置ORACLE_HOME环境变量这个写法会报ORACLE_HOME is not set。我习惯把环境变量先导出再检查$ORACLE_HOME/OPatch/opatch version能正常输出确保当前终端会话指向的是正确的软件目录。多个实例共机的环境这一步尤其重要。3. 应用补丁标准流程从环境备份到post-install脚本的完整命令链3.1 第一阶段备份和空间检查给后悔药留好后路任何补丁操作前先确认两件事ORACLE_HOME的备份方式和磁盘剩余空间。补丁本身几百兆到几个G不等但应用时OPatch会先制作文件备份加上解压后的临时文件实际占用往往是补丁包大小的两倍以上。df -h $ORACLE_HOME tar -czf /backup/oracle_home_$(date %Y%m%d).tar.gz $ORACLE_HOME第一行检查ORACLE_HOME所在文件系统的可用空间第二行做ORACLE_HOME整体备份。有人觉得ORACLE_HOME太大没必要备份只备份$ORACLE_HOME/OPatch和$ORACLE_HOME/bin下的内容这种做法不是不行但恢复时容易缺文件。全量备份是笨办法不过胜在简单可靠我用它兜底。数据库软件层面的备份做完还要考虑数据字典层面如果补丁说明要求执行post-install SQL脚本那数据库本身的可恢复点也值得考虑。常规做法是开启归档日志然后做一个全库备份或者至少确保最近的可用备份存在。这里注意备份与补丁操作之间最好不安排其他变更避免备份里混入半变更状态的文件恢复时反而引入新的不一致。3.2 第二阶段停库并执行opatch apply根据README要求大多数11g季更补丁需要在数据库关闭状态下应用。这里要区分单实例和RAC单实例直接shutdown immediateRAC则要求按节点顺序处理第3.4节会单独说明。sqlplus / as sysdba SQL shutdown immediate; SQL exit cd /u01/app/oracle/product/11.2.0/dbhome_1 unzip -o /patch_src/p20760997_112030_Linux-x86-64.zip -d /tmp/patch_dir cd /tmp/patch_dir/20760997 $ORACLE_HOME/OPatch/opatch apply这里的unzip解压目录不要放在ORACLE_HOME内部避免OPatch扫描时把解压出来的文件当成已存在的补丁内容apply命令在补丁目录内执行OPatch会读取该目录下的补丁描述文件。参数上没有特殊开关常规安装直接apply即可遇到README要求使用napply的场景把apply换成napply作用区别是apply用于单个补丁napply用于一次应用多个独立的补丁且不产生排序冲突。执行apply时建议用tee保留输出命令可以写成$ORACLE_HOME/OPatch/opatch apply | tee /tmp/opatch_apply.log。输出内容很长重点看两个位置开头是否通过Prerequisite check结尾是否出现OPatch succeeded。中间出现的WARNING多与文件权限或历史记录相关往回翻日志时看到某个文件被反复更新可以回到补丁目录再比对时间戳。关于是否停库强烈建议以README为准。某些一次性补丁支持在线应用数据库可以保持open状态但OPatch仍会短暂占用文件句柄。我在生产环境的原则是能停就停停库时间选在低峰期比赌在线补丁更省心。3.3 第三阶段post-install脚本数据字典更新必须手工触发apply成功并不代表补丁装完了。很多季更和PSU补丁带一个post-install阶段需要手工执行SQL脚本把新的数据字典视图、PL/SQL包变更灌入数据库。11g中常见脚本路径是$ORACLE_HOME/rdbms/admin下的catbundle.sql参数为补丁名。sqlplus / as sysdba SQL startup; SQL spool /tmp/catbundle_apply.log SQL ?/rdbms/admin/catbundle.sql psu apply SQL spool off SQL exitcatbundle执行时间取决于数据库大小和数据字典规模从二十分钟到数小时不等。这里的参数psu表示应用的是PSU类补丁apply是动作路径中的?号由SQL*Plus自动替换为ORACLE_HOME。执行前注意把数据库探测的符合补丁版本的字典版本写入bundle信息后续用脚本核对很方便。日志里出现的ORA-错误如果只是在某些已存在对象上的重复编译警告通常可以忽略但如果是ORA-04021之类的对象锁错误就要查会话。另外post-install脚本执行期间不要让其他会话修改数据字典比如创建用户或重建索引这类操作会与脚本产生锁竞争严重时导致脚本回滚。3.4 RAC环境多节点操作的顺序一次只动一个节点多节点环境不能在所有节点同时跑opatch apply正确顺序是节点1打补丁完成后再启动节点2。两个节点同时动ORACLE_HOME下的二进制文件节点间会出现文件版本不一致虽然监听和ASM实例可能还能跑但应用会间歇性报错这类故障非常难排查。# 节点1 sqlplus / as sysdba SQL shutdown immediate; SQL exit $ORACLE_HOME/OPatch/opatch apply # 节点1执行完启动数据库并验证实例状态再切到节点2重复同样流程节点切换期间数据库继续由另一个节点对外服务这就是滚动打补丁的思想。11g的PSU季更多数不支持自动滚动需要按上述手工方式滚动。节点1恢复后用srvctl status database检查实例注册状态确认服务正常接管再开始节点2的操作。两个节点的补丁版本最终要一致否则OCR里的版本信息与实例实际版本对不上后续执行集群命令可能报版本不匹配。4. 回滚与常见问题排查三个翻车现场现象原因和解决都记在这4.1 回滚操作opatch rollback的边界条件如果补丁应用后验证发现问题回滚是第一手段。opatch rollback的基本命令是$ORACLE_HOME/OPatch/opatch rollback -id 20760997-id参数后面跟补丁号OPatch会读取应用记录。这里有个前提只有OPatch生成的文件备份完好回滚才可能成功。所以不要为了省空间把$ORACLE_HOME/OPatch/cfgtoollogs/opatch目录清掉那里存有每次安装的记录清理动作相当于自断后悔药。回滚前先执行opatch lsinventory确认目标补丁号在列表里$ORACLE_HOME/OPatch/opatch lsinventory | grep -i 20760997如果列表里没有这个补丁号说明应用记录不完整直接回滚会报patch not found。解决思路是先检查是否打错了ORACLE_HOME或者补丁号输入有误。这个检查动作几秒钟能避免在错误的方向上浪费时间。回滚完成后同样要检查README中是否有对应的post-rollback脚本。很多情况下回滚比安装更敏感我见过回滚后半数节点字典版本一致但个别节点遗留了旧版本对象的情况原因是回滚前没有做全量备份中途文件冲突被跳过。回滚之后重新启动数据库按第5章的验证清单快速过一遍再放业务流量。4.2 坑一opatch apply报OPatch version check failed现象执行apply后秒退输出显示OPatch版本过低实际环境明明已经跑过许多补丁。原因这类报错有两个来源一是ORACLE_HOME中实际生效的OPatch并不是$ORACLE_HOME/OPatch下这个可能是PATH环境变量里先找到了另一个ORACLE_HOME的OPatch二是目标补丁要求的OPatch版本比环境中高出很多而之前的补丁都只需要老版本。解决先执行which opatch确认调用链再直接用绝对路径调用目标ORACLE_HOME下的opatch。如果version仍然低就升级OPatch工具升级后顺手跑一遍opatch lsinventory确认应用记录还在。还有一种情况是ORACLE_HOME路径本身包含软链接OPatch解析后的路径与预期不一致处理方法是在补丁目录下用pwd -P确认实际物理路径。4.3 坑二磁盘空间明明够apply却死在解压阶段现象df -h看到ORACLE_HOME所在分区还有几十G但unzip或apply阶段报no space left on device。原因很可能是临时目录被占满。/tmp默认大小可能有限尤其是一些加固过操作系统的机器把/tmp挂成了独立小分区。解决解压前用df -h /tmp和df -h $ORACLE_HOME分别确认临时目录不够就用环境变量改到ORACLE_HOME内部的空间export TMPDIR/u01/app/oracle/tmp mkdir -p $TMPDIR把unzip的目标目录也放到TMPDIR下再执行apply。这里补充一个细节OPatch在应用补丁时会向$ORACLE_HOME/.patch_tmp目录写入临时文件如果该目录所在文件系统inode耗尽也会表现成磁盘空间不足。检查时顺手执行df -i看一眼inode使用率判断是容量问题还是inode问题两个方向的处理方式完全不同。4.4 坑三conflict detected之前的一次性补丁和新补丁冲突现象apply过程中出现conflict列表列出已经安装的某个补丁号并中止。原因目标补丁包含了历史补丁中修复的代码变更数据库环境已经把旧补丁打进去了继续应用会重复覆盖。解决根据README的建议操作。常见做法是先回滚被点名的冲突补丁再应用新补丁如果README说明可以直接强制应用用opatch apply -force但前提是把影响范围确认好。我不建议无脑-force做之前对比一下冲突补丁和当前补丁的描述看是不是同样的问题域。冲突处理之后重新执行lsinventory确认剩余补丁集合符合预期。force参数的本质是跳过冲突检测但它不会解决文件层级的重复覆盖问题。如果两个补丁修改的是同一个文件强制应用后该文件可能包含旧补丁的代码也可能只包含新补丁的代码取决于打包顺序。所以force只适合README明确指出的场景其他情况一律先回滚再应用。4.5 补丁栈的一致性记录防止下个季度打补丁时找不着北每个季度更新后把opatch lsinventory -oh $ORACLE_HOME的输出保存一份带日期的文本。下次应用补丁前可以快速对比当前补丁基线判断是否存在遗漏或多余补丁。这个动作成本极低但节省排查时间的效果显著我把它列为打补丁后的固定动作之一。$ORACLE_HOME/OPatch/opatch lsinventory -oh $ORACLE_HOME /backup/patch_baseline_$(date %Y%m%d).txt ls -l /backup/patch_baseline_*.txt | tail -3保存文件命名带上日期配合补丁归档目录就能还原每个季度环境所处的补丁状态。遇到问题需要回溯时先看基线文件里当时装过哪些补丁再定位代码变更范围比直接翻历史工单快很多。5. 补丁验证从实例状态到失效对象逐项核对才叫装完5.1 实例层面的验证版本一致性检查和实例状态补丁装完数据库能启动只是第一关。对11g来说要检查v$version视图确认补丁版本已经写进数据库内部版本码。sqlplus / as sysdba SQL startup; SQL select banner from v$version; SQL select comp_id, version, status from dba_registry;dba_registry的输出中每个组件的status应当是VALIDversion应当符合补丁说明中的版本要求。如果出现INVALID或者UPGRADE状态说明post-install脚本没跑到位或者有组件更新失败需要回到第3.3节的步骤。这里要注意v$version和dba_registry的更新时机不同v$version显示的是数据库软件内部版本补丁应用后一般会更新dba_registry记录的是数据字典层面注册的组件版本需要post-install脚本正确执行。两个视图不一致的情况在漏跑catbundle后经常出现这也是把二者都列上验证清单的原因。启动后还要关注alert日志。补丁后第一次启动alert日志里可能出现ORA-600内部错误或者Errors in file之类的内容这些往往与某个文件版本不匹配相关。我的做法是启动完成后用tail命令看alert日志末尾50行确认没有新的错误刷出再继续后续验证。5.2 失效对象扫描把编译警告变成可量化清单补丁更新过程中可能使某些视图或包处于INVALID状态。正常的更新流程会通过脚本自动重编译大部分对象但个别依赖顺序复杂的对象可能留下需要手工编译。sqlplus / as sysdba SQL select owner, object_type, count(*) from dba_objects 2 where statusINVALID group by owner, object_type;这个查询直接量化了失效对象。如果结果非空使用utlrp.sql重编译sqlplus / as sysdba SQL ?/rdbms/admin/utlrp.sqlutlrp执行完重跑一遍失效对象查询余下的对象单独查dba_objects的last_ddl_time判断是否补丁时间之前就存在的老失效对象。这类遗留失效对象与本次补丁无关可以按历史问题单独处理不用惊慌。对比补丁安装前后两份失效清单比对着满屏INVALID猜测来源要高效得多。utlrp脚本默认串行重编译对象数量大时耗时较长。可以先用select count(*) from dba_invalid_objects确认总量如果上千个对象可以调整并行度。11g中常见做法是通过job队列并行跑但并行度过高会与业务进程抢资源我在生产环境一般控制在4个并发以内重编译任务跑在业务低峰期。5.3 系统相关参数的比对初始化参数与补丁后基线部分补丁会调整隐含参数或新增系统参数但不会自动修改spfile。验证时把补丁前后的参数差异拉出来检查sqlplus / as sysdba SQL create pfile/tmp/pfile_after_patch.ora from spfile;用diff命令对比补丁前导出的pfile和补丁后的pfile重点看新增的参数行。如果新增参数不是sga_target这类公开参数而是下划线开头的隐含参数就要回README里查该参数的作用避免环境带着未声明的行为变化运行。参数对比时注意不要只看名称还要看单位。补丁有时会把某个资源限制参数从字节改成百分比数值看起来变了实际效果相同。这类变化在diff中很容易被误判为异常处理方式是回到README确认参数变更说明没有说明的再查文档。5.4 应用侧冒烟测试连接会话和典型业务语句各跑一遍数据库层验证完毕后最好做一次应用侧冒烟测试。连一个业务账号跑一条典型的查询、插入和事务提交确认应用连接正常锁与等待事件没有异常增长。这一步不能省因为我见过补丁安装成功、字典也干净但应用连接池无法获取连接的情况原因是补丁更新了数据库驱动兼容性要求应用侧JDBC版本偏旧。冒烟测试能提前暴露这类集成层面的问题。sqlplus apps/apps_pass//localhost:1521/ORCL SQL select count(*) from dual; SQL insert into smoke_test values (sysdate); SQL commit; SQL select * from v$session_wait where wait_class ! Idle;冒烟测试的时间窗口不用太长重点验证连接建立、事务提交、无异常等待三段路径。v$session_wait的查询用来确认没有大量非空闲等待会话堆积。如果这个查询返回很多行说明应用侧存在阻塞需要进一步查blocking_session定位源头。6. 补丁包解压校验与归档拿到zip后先做的三个动作遇到新下载的补丁包我从不直接解压先做三件事校验完整性、查看文件清单、归档原始压缩包。校验完整性的命令常用md5sum或者cksum与下载页面给定的哈希值对比。哈希对不上就先别装补丁包损坏或下载中断都会导致解压即报错省得浪费时间在假故障上排查。文件清单的查看用unzip -l重点确认zip内部是否只有一个补丁目录还是包含多个补丁和工具包。有些批次资源把OPatch更新包和补丁包合并压缩解压后目录里出现两个编号这时候先装工具包再装补丁。归档原始压缩包则是一个长期习惯把补丁包按日期和版本命名归档例如patch_20760997_112030_2025Q1.zip下季度再处理时直接能找到历史基线。归档目录建议保持三级结构平台、版本、补丁号检索成本最低。从那以后我每次打补丁都强制走一遍文件名解析、README三行笔记、opatch version确认、空间与备份、停库apply、post脚本、验证清单、归档原始包。这套流程看着啰嗦但每个季度用一次换来的是补丁操作的可预期。希望帮到你。本文还有配套的精品资源点击获取