简介:面向64位Linux平台维护Oracle 11g R2数据库的管理员,这是一份编号24006111的季度补丁包,对应11.2.0.4.161018版本。该版本发布于2016年10月,用于集中修复上一个季度以来的已知问题,强化安全防护并改善运行性能,是生产环境保持稳定高效的重要更新。压缩包整体约100.6MB,文件总数与具体类型暂未收录,但通常包含补丁说明、依赖校验信息以及核心升级程序,安装时需配合Oracle官方Opatch工具进行验证与部署。Oracle遵循季度累积发布策略,因此该包涵盖自上一补丁起的所有修复,管理员无须在大量零散补丁中逐一查找,可显著缩短维护窗口内的操作时间。目前已有265人学习下载,适合数据库运维工程师、系统管理员以及需要理解Oracle季度补丁机制或执行系统升级的DBA参考。通过这份补丁包,读者可以核对系统兼容性、规划备份与停机窗口,借助Opatch完成升级,并了解失败时的排查与回滚方法;对于涉及ASM、RAC等组件的环境,也能以此为基础实施安全加固,降低生产变更风险。
1. p24006111_112040_Linux-x86-64.zip:一个 Oracle 补丁包的自我修养
拿到这个文件名,先别急着双击解压。p24006111_112040_Linux-x86-64.zip 是 Oracle 数据库补丁的标准命名:p 开头是补丁包固定前缀,24006111 是补丁号,112040 对应 11.2.0.4.0 这个版本,Linux-x86-64 指明平台。也就是说,这是给 Linux 64 位环境下 Oracle 11gR2 数据库用的补丁包。补丁不是下载完就能直接装的——传输损坏、磁盘空间不足、属主不对、前置补丁缺失,每一个坑都可能让生产库无谓地多停一次。这篇文章从校验、解压、安装、验证到批量分发,把这条链路完整走一遍,适合正在维护老版本 Oracle 库的 DBA 和运维工程师,也适合第一次独立给 Linux 服务器打补丁的年轻人照着做。
2. 动手前先验货:用 linux 常用命令把 zip 补丁包核清楚
2.1 为什么先校验而不是直接解压:zip 包在半路翻车的几种可能
在 Linux 上处理 Oracle 补丁包,我养成的第一个习惯是:解压之前,先把校验做了。zip 这个格式本身带 CRC32 校验,但它在跨网络传输时并不会自动保证文件完整。FTP 中断、SFTP 超时、scp 传一半网络闪断,或者下载工具断点续传时写坏了字节,都会让补丁包到服务器上时已经不是官方发布的原样。
最典型的现象是解压到一半报cannot find zipfile directory,或者unzip: bad zipfile offset。这时候第一反应不是怀疑命令用错了,而是文件在传输链路上出了问题。Oracle 补丁包动辄几百 MB,从官网下载到本地、再从本地推到服务器,中间经手的人越多,翻车概率越高。很多同事喜欢只看文件大小,大小一致就觉得稳了,其实 zip 的中央目录记录在文件末尾,尾部损坏时文件总大小可能一字节不变,但内部结构已经坏了。
所以我的步骤永远是:先md5sum对值,再unzip -t测完整性,最后才实际解压。这三级检查不花多少时间,但能省掉后面 opatch 装到一半报错的几小时排查。下面把每一条命令的具体用法和输出讲清楚。
2.2 md5sum、unzip -t、unzip -l:解压前必跑的三条命令
先看 md5sum 怎么用。下载补丁的页面或邮件里通常会附带一个 CHECKSUM 文件,里面有这个 zip 包的 MD5 值。对比方法很简单:
# 假设补丁包放在 /u01/patches 目录 md5sum /u01/patches/p24006111_112040_Linux-x86-64.zip # 输出示例: # 9a2f7c1b7e4d5a8f6c0d1e2f3a4b5c6d /u01/patches/p24006111_112040_Linux-x86-64.zip把屏幕上输出的 MD5 值和官方给的比对,完全一致才继续。这个命令计算的是整个文件内容的摘要,只要有一个 bit 变化,输出的 32 位十六进制字符串就会完全不一样。所以我从不在这一步节省时间,特别是补丁包经手人比较多的时候,每多一道拷贝,就多一分出错风险。
md5sum 通过后,再用 unzip 自带的功能测试压缩包内部结构:
# -t 表示 test,只做校验不实际解压,逐个文件比对 CRC32 unzip -t /u01/patches/p24006111_112040_Linux-x86-64.zip # 正常时末尾会输出: # No errors detected in compressed data of p24006111_112040_Linux-x86-64.zip-t会遍历 zip 包里的每个文件,重新计算 CRC32 并与压缩包内记录的值比对。如果 MD5 是通过的,这条命令一般也会直接通过,但多看一眼没有坏处。md5sum 校验的是文件整体,unzip -t 校验的是 zip 内部结构和每个文件的数据块。zip 的目录指针偏移损坏时,md5sum 不一定会暴露问题,而 unzip -t 会老老实实告诉你。
然后才是看内容清单:
# -l 列出 zip 包内文件清单,不展开内容;head 限制输出行数,防止文件太多刷屏 unzip -l /u01/patches/p24006111_112040_Linux-x86-64.zip | head -30这一步的意义在于确认包内结构和预期一致。Oracle 补丁包的 zip 里一般会包含一个以补丁号命名的顶层目录(比如24006111/),里面有 README.txt、files/、etc/、custom/等子目录。如果解压出来的顶层目录名不是补丁号,或者 README 的位置和以往见到的不一样,说明这个包可能被二次打包过,要谨慎处理,最好回到官方源重新下载。
这里顺带说一个容易忽略的差异点:不同发行版自带的 unzip 版本不同。CentOS、Ubuntu、openSUSE 上的 unzip 对中文文件名的处理、对大文件 4GB 上限的支持、对 zip64 扩展的支持都不一样。用 Oracle 补丁包时因为文件名基本都是 ASCII,碰到的概率低,但如果拿到一个别人从 Windows 那边转发的 zip,就可能在参数选择上踩坑。这个放在后面避坑章节细讲。
2.3 解压后第一件事:读 README,而不是直接跑 opatch
校验没问题,就可以解压了。我习惯单独建一个目录,避免 zip 里的文件散落到当前路径:
cd /u01/patches mkdir p24006111 # -d 指定解压目标目录,把 zip 内容全部释放到 p24006111 子目录下 unzip p24006111_112040_Linux-x86-64.zip -d p24006111解压完成后不要急着切换用户、进opatch apply。先把 README 找出来读一遍:
# 在解压出来的目录里定位 README,文件名通常是 README.txt unzip -l p24006111_112040_Linux-x86-64.zip | grep -i readmeREADME 里需要重点看三块内容。第一是补丁的前置条件,比如基础版本必须是 11.2.0.4.0 以上、要求已经安装了某个更早的补丁、要求 OPatch 工具的最低版本,这些条件不满足,opatch 会在检查阶段直接失败。第二是补丁类型和应用方式,有些补丁需要停库、有些支持在线应用,OJVM 类的补丁通常要求在实例关闭状态下应用。第三是回滚说明,补丁是否支持 rollback、回滚需要什么前置条件,都写在这一段里。
这里特别提醒,不要在没读 README 的情况下直接执行opatch apply。我在生产环境见过不止一次,有人拿到补丁包就按网上搜到的通用流程跑,结果在Prerequisite check阶段被拦下来,然后回头补看文档,才发现是少了前置补丁。补丁包自带的 README 是当前环境唯一准确的安装依据,比任何博客都权威。花十分钟读完,后面能省下半天到一天的折腾。
3. 从 zip 到已生效补丁:opatch 装补丁的完整命令链
3.1 打补丁前的环境体检:opatch version 与 ORACLE_HOME 的确认
补丁解压校验通过,接下来才是重头戏——用 opatch 把补丁真正装进 Oracle 软件目录。opatch 是 Oracle 自带的补丁管理工具,它负责解包、检查依赖、替换二进制文件、更新 inventory 清单。装补丁之前,先给自己的环境做一个快速体检。
# 确认当前用户的 ORACLE_HOME 环境变量 echo $ORACLE_HOME # 期望输出:/u01/app/oracle/product/11.2.0/dbhome_1 # 如果没有输出,说明没有加载 oracle 用户的环境配置 # source ~/.bash_profile 后再检查ORACLE_HOME 没配好,后面所有命令都会跑偏。很多服务器上同时装了多个版本的数据库,环境变量串了,opatch 可能打到错误的软件目录上。所以我会再检查一下 opatch 本身:
# 查看 OPatch 工具自身版本,11.2.0.4 数据库要求 OPatch 不低于某个版本 $ORACLE_HOME/OPatch/opatch version # 输出示例: # OPatch Version: 11.2.0.4.15OPatch 版本不够时,opatch apply 会直接提示。常见做法是单独下载最新的 OPatch 工具包,解压后替换到$ORACLE_HOME/OPatch下。这个工具包也是一个 zip,命名类似p6880880_112000_Linux-x86-64.zip,在官方支持站点可以检索到。替换 opatch 本身不算打补丁,但它是很多补丁的前置要求,这里提一句,后面排查章节还会遇到。
体检最后一步,确认补丁目录里的 inventory 信息能被 opatch 正确读取:
# 列出当前 ORACLE_HOME 已安装的补丁,确认系统当前状态 $ORACLE_HOME/OPatch/opatch lsinventory -oh $ORACLE_HOME这条命令会输出已经打过的补丁列表和 OPatch 版本。如果这个列表和你预期的历史记录对不上,先解决 inventory 的问题再继续,否则补丁打进去之后,出现多个补丁互相覆盖时,复盘会非常困难。
3.2 停监听、备份、打补丁:最小可执行流程
环境确认完毕,进入正式流程。对 11.2.0.4 这类老版本库,大多数补丁要求在实例关闭状态下应用。我的执行顺序如下:
# 第一步:关闭监听,防止新连接涌入 lsnrctl stop # 第二步:关闭数据库实例 sqlplus / as sysdba SQL> shutdown immediate; SQL> exit关闭实例前,建议先确认没有活动的长事务。shutdown immediate会等待当前 SQL 结束,如果业务上有跑了几小时的长任务,这里可能卡住很久。稳妥做法是提前和业务方确认窗口,然后在停库前用select count(*) from v$session where status='ACTIVE'看一眼活跃会话。生产环境最怕的是 shutdown 卡住,强杀实例又容易留下恢复日志,这个风险要在停库前规避掉。
实例关闭后,做备份。补丁改的是$ORACLE_HOME下的二进制和脚本,不碰数据文件,但为了后悔药起见,我还是会打包整个 ORACLE_HOME:
# 第三步:备份 oracle home,时间戳区分不同批次 tar czf /backup/orahome_$(date +%Y%m%d_%H%M%S).tar.gz $ORACLE_HOME这一步看起来简单,但有两点要注意:第一,打包前把$ORACLE_HOME下的 trace 文件、log 文件清一清,否则 tar 会非常大;第二,如果数据库是 RAC,每台节点都需要独立打包,因为每台节点的 ORACLE_HOME 内容不完全一样。备份的目的是在补丁安装失败时能快速恢复原状,所以这个包不要放在 oracle home 同一个分区下,放到独立备份盘更稳妥。
备份完成,正式应用补丁:
# 第四步:进入补丁目录执行 apply cd /u01/patches/p24006111/24006111 # -oh 显式指定 ORACLE_HOME,避免环境变量混乱时打错地方 # 不加 -silent 时,opatch 会在检查通过后要求输入 y 确认 $ORACLE_HOME/OPatch/opatch apply -oh $ORACLE_HOMEopatch apply 的执行过程大致分几个阶段:先做环境检查和补丁依赖检查,然后备份即将被替换的二进制文件到 patch 目录下的 backup 区域,接着拷贝新文件到$ORACLE_HOME对应的库目录,最后更新 inventory。整个过程快则几分钟,慢则二十分钟,取决于补丁类型和机器磁盘性能。
这里特别说一个细节:opatch apply最好在补丁目录内部执行,也就是刚才命令里 cd 进去的那个目录。如果不进去,也可以用-ph参数显式指定补丁路径。我一般两种都行,但更习惯 cd 进去,因为这样后面查看日志时路径更直观。opatch 默认会在当前目录下生成日志文件,如果工作目录不确定,日志路径会变得很乱,排错的时候找起来费劲。
打完之后,按 README 的 Post-Installation 要求执行后续脚本。常见的 11.2.0.4 补丁会要求在数据库启动后执行catbundle.sql或utlrp.sql。这一步不能省略,补丁的 SQL 变更要在这个阶段写入数据字典,只装二进制不跑脚本,补丁等于没生效。
# 第五步:启动实例和监听 sqlplus / as sysdba SQL> startup; SQL> exit lsnrctl start3.3 opatch apply 的关键参数:-oh、-ph、-invPtrLoc 什么时候用
参数这块单独拎出来讲,是因为我在多套环境上见过因为参数不对导致补丁装错地方的例子。-oh是最常用也最重要的参数,它指定目标 ORACLE_HOME。当服务器上安装了多个数据库版本,或者当前 shell 的环境变量已经被别家污染时,不加这个参数就等于让 opatch 猜,猜错的后果就是新二进制被拷贝到错误的目录,inventory 记录也乱了。
-ph指定补丁所在路径。opatch 默认在当前工作目录找补丁,如果执行环境不是在补丁目录内,就要显式指出来。批量脚本里用自动化工具跑 opatch 时,-ph几乎是必须的,因为脚本可能在任何目录被调用。
-invPtrLoc指定 oraInst.loc 的路径。这个文件记录了 Oracle inventory 的位置,一般位于/etc/oraInst.loc。当环境变量ORACLE_HOME正常时,opatch 能自动找到它;但如果系统里用到了 OUI 的替代 inventory 位置,或者是从别的机器拷贝过来的 oracle home,就需要显式指定。出现这个参数的使用场景通常比较罕见,但一旦需要却没有用,opatch 会直接报找不到 inventory,和权限问题混在一起,很容易让人走弯路。
对 RAC 环境,还有一个参数值得记住:-local。它让 opatch 只更新当前节点的 ORACLE_HOME,不影响滚动集群里的其他节点。在 Oracle 11g 上给 RAC 打补丁,普遍做法是逐节点应用:先在一个节点上用opatch apply -local打完,确认无异常,再切换服务到下一个节点继续。这种方式比在共享存储上直接改二进制安全得多。后面分发章节我会再展开讲怎么组织这个流程。
4. 常见踩坑与排查:Linux 上装 Oracle 补丁的 5 条血泪记录
4.1 unzip 报 cannot find zipfile directory:多半是文件没传完
现象:在 Linux 上执行unzip p24006111_112040_Linux-x86-64.zip,开头就报cannot find zipfile directory in this archive,或者解压到一半突然中断。
原因:zip 的中央目录在文件末尾,文件没传完整、磁盘写入失败、下载工具超时中断,都会导致末尾缺失。很多时候文件大小看起来差不多,但末尾的几十字节丢了,unzip 就找不到目录指针。
解决:先删掉这个文件,重新从源地址用 SFTP 或 rsync 传输一次。传完立刻md5sum与官方值比对,比对通过再解压。不要在原文件上尝试修复,zip 的自我修复能力有限,浪费的时间不如重新下载。如果是内网机器,从跳板机拷贝时建议用 rsync,因为它有断点续传和完整性校验,比 scp 在这个场景下更可靠。
4.2 opatch 报 Prerequisite check failed:版本不匹配,不是玄学
现象:opatch apply跑了几秒钟就退出,提示某个Prerequisite checkfailed,有时还附一句Expected: 11.2.0.4.0, Found: 11.2.0.3.0或类似字样。
原因:补丁要求的基础版本、前置补丁、OPatch 版本任一不满足。11.2.0.4 补丁对数据库基础版本有严格要求,如果系统实际是 11.2.0.3,必须先升级到 11.2.0.4 才能打这个补丁。另一种情况是缺少更早的补丁,比如某个 PSU 必须要求先打上一个季度的 CPU,跳过之后当前补丁检查不通过。
解决:打开补丁目录下的 README,找到Prerequisites一节,逐条对照当前环境。用$ORACLE_HOME/OPatch/opatch lsinventory看已安装补丁列表,确认前置补丁是否在列。如果确实是 OPatch 版本不够,按 3.1 节方法更新 OPatch 再重试。这里最忌的是用opatch apply -silent -force这类方式强过检查,跳过前置检查打出来的补丁很可能在运行期暴露问题,到时定位成本远高于老老实实补前置。
4.3 /tmp 被占满:解压到一半失败的经典原因
现象:解压补丁包时,文件释放到大约 50% 的位置报No space left on device,但用df -h看/u01/patches明明还有很多空间。注意,unzip 解压时的临时目录未必是目标目录,特别是在某些环境下/tmp被 bind mount 到了小分区。
原因:解压过程本身有时需要临时空间,Oracle 补丁包内的文件数量多,解压时文件系统元数据也可能吃紧。更常见的场景是/tmp分区只有 2GB,而补丁包解压后是 4GB,unzip 在工作目录或临时目录里做缓冲,把小分区撑爆。
解决:先用df -h /tmp看剩余空间,再决定调整方式。如果你的 unzip 支持环境变量,可以设置TMPDIR=/u01/tmp指向大分区;或者干脆把解压目标直接指向大分区,比如unzip xxx.zip -d /u01/bigspace/patches。解压前用unzip -l看包内文件总大小,估算一下释放后占用,再对照目标分区空间,这一步能避免一半以上的中途失败。顺手把过期的旧补丁包和 trace 清理掉,也是日常空间管理的一部分。
4.4 文件属主不对:root 解压的 zip,oracle 用户打不了补丁
现象:解压成功,但切换成 oracle 用户执行opatch apply时报权限错误,日志里出现java.io.IOException: Permission denied或cannot write file。
原因:zip 包是在 root 用户下解压的,解压出来的文件属主是 root,oracle 用户对目录没有写权限。Oracle 补丁应用过程要替换$ORACLE_HOME下的二进制,这些操作必须以 oracle 用户(通常是软件属主)身份执行,权限不足就直接失败。
解决:解压完成后统一调整属主,再继续后续操作:
# 把整个补丁目录及内部文件的属主交给 oracle 用户 chown -R oracle:oinstall /u01/patches/p24006111 # 同时确认 ORACLE_HOME 本身的属主没有被改动 chown -R oracle:oinstall $ORACLE_HOME这里有一个容易被忽略的点:chown -R是递归修改,但只对已经存在的文件生效。如果 zip 包里有符号链接,或者解压过程产生了断链文件,chown 之后再解压覆盖,新文件属主又会变回 root。所以我的习惯是先解压、再 chown、然后做一次ls -l抽查,确认属主无误后再碰 opatch。这些步骤在补丁目录的文件数量特别多时尤其重要,不要相信一条 chown 能覆盖所有意外。
4.5 zip 伪加密和中文文件名乱码:Windows 制作补丁包的两个例外
现象:解压时提示需要密码,或者报unsupported compression method 99;另一种情况是解压出来的文件名变成一串乱码,比如�����.txt。
原因:zip 文件有一个加密标志位,某些 Windows 端的压缩工具处理过的 zip 会把标志位置为加密,但文件内容实际上没有加密,这就是俗称的 zip 伪加密。另一种情况是压缩包内文件名编码是 GBK,Linux 的 unzip 默认按 UTF-8 解码,于是文件名全部显示成乱码。Oracle 官方补丁包不会出现这两种情况,但如果是别人从 Windows 复制粘贴转发的二次打包文件,就可能遇上。
解决:遇到伪加密,优先用 7-Zip 处理:
# 先用系统自带的包管理安装 p7zip # yum install p7zip 或 apt install p7zip-full # 用 7z 解压,它不校验伪加密标志,直接按实际内容释放 7z x p24006111_112040_Linux-x86-64.zip -o/u01/patches/p24006111遇到中文乱码,可以尝试 unzip 的-O参数指定编码:
# -O CP936 告诉 unzip 用 GBK 解码文件名(部分发行版编译时才启用该选项) unzip -O CP936 p24006111_112040_Linux-x86-64.zip -d p24006111如果当前系统的 unzip 不带-O选项,用 Python 的 zipfile 模块是另一个可选路径:
# python3 处理文件名为 GBK 编码的 zip import zipfile z = zipfile.ZipFile("p24006111_112040_Linux-x86-64.zip") for name in z.namelist(): real_name = name.encode('cp437').decode('gbk') z.extract(name, "/u01/patches/p24006111")这里说明一下,Python 的 zipfile 在读取不含 UTF-8 标志的文件名时,默认用 cp437 解码,所以要先对文件名做一次编码转换。这个解法对 Oracle 补丁包其实是用不到的,但排查问题的过程中能想到这种层级,说明对 zip 格式本身有系统的认知,应付非官方渠道拿到的包时会从容得多。
5. 补丁打完了怎么验证:opatch lsinventory 与 SQL 查询配合
5.1 opatch lsinventory 的过滤参数:-bugs_fixed、-oh、-detail
补丁装完,重启实例和监听,这不算结束。验证补丁是否真实生效,要从工具和数据字典两个层面确认。先看 opatch 自己的视角:
# 过滤查看当前环境已经固定的 bug 列表,按补丁号精确匹配 $ORACLE_HOME/OPatch/opatch lsinventory -oh $ORACLE_HOME -bugs_fixed | grep 24006111 # 如果只想看整体列表,用 -detail 输出每个补丁的详细信息 $ORACLE_HOME/OPatch/opatch lsinventory -oh $ORACLE_HOME -detail-bugs_fixed会列出该补丁修复的所有 bug 号,而过滤条件 24006111 匹配的是补丁号本身。如果输出里有相关记录,说明补丁已经登记到 Oracle 的 inventory 中,二进制替换也完成了。注意,opatch lsinventory 查的是 ORACLE_HOME 层面的记录,它无法证明 SQL 脚本已经在数据库里执行过,这一步要用下一个小节的数据字典来完成。
这里还有一个判断技巧:如果补丁安装时中途报错,但 opatch 显示补丁已存在,说明 inventory 记录可能已经写入而二进制替换不完整,这种状态最危险。我的做法是记录opatch lsinventory输出的时间戳和日志文件位置,万一后续排查需要,能快速回溯到当时的实际状态。
5.2 数据字典确认:dba_registry_sqlpatch 与 registry$history
SQL 脚本是否执行,直接查数据字典最可靠。以 sysdba 身份登录数据库,执行:
-- 查看补丁在 SQL 层面的注册记录 select patch_id, patch_uid, action, status, description from dba_registry_sqlpatch where patch_id = 24006111;正常的输出里,action 是APPLY,status 是SUCCESS。如果查不到记录,说明补丁包内的 SQL 变更还没有注册进数据字典,需要回到 README 的 Post-Installation 章节,找到对应的catbundle.sql或类似脚本重新执行。
另一个视图registry$history记录了更底层的变更历史:
-- 从历史表确认补丁相关的 DDL 和版本变化 select id, comments, action_time, namespace, version from registry$history where id = 24006111;这两张表配合起来看,能确认补丁的 SQL 层面确实生效,而不是只更新了二进制。对 11.2.0.4 上的补丁来说,这一步尤其重要,因为很多 PSU 和 OJVM 补丁的变更集中在 JVM 组件上,光看二进制替换无法发现漏跑脚本的问题。
5.3 无效对象与 utlrp.sql:最后一道工序
补丁装完后,数据库里偶尔会出现无效对象。这不是补丁失败的标志,很多补丁会更新内部对象导致状态变化,需要重新编译。查一下现状:
-- 按属主和对象类型统计无效对象数量 select owner, object_type, count(*) from dba_objects where status = 'INVALID' group by owner, object_type;如果存在无效对象,执行 Oracle 自带的编译脚本:
-- utlrp.sql 会以并行方式重新编译所有无效对象 @?/rdbms/admin/utlrp.sql脚本执行完,再跑一遍统计,确认无效对象数量降为正常水平。这里不用追求零无效对象,某些组件(比如 SYS 下的部分 Java 类)在打补丁后需要等到第一次实际使用才触发编译,少量残留是正常的。关注的是数量级是否异常,如果从 0 变成几千个,那就要回 opatch 日志认真排查了。
验证流程走完,再观察一段时间的告警日志,重点看有没有新增的 ORA 错误。补丁生效与否,最终要由线上行为来背书。验证这一步做得越细,后续回溯时越有底气。
6. 一人管几十台 Linux:补丁分发、校验与回滚的操作习惯
6.1 rsync 分发补丁包的参数选择:-avz 与 --timeout
当你需要同时给多台 Linux 服务器打同一个补丁,效率和安全就变成一对矛盾。我的做法是先把补丁包用 rsync 推送到所有目标机,再做统一校验,最后逐台打补丁。
# 从跳板机分发到数据库服务器,-a 保留属性,-v 显示过程,-z 压缩传输 # --timeout=60 防止连接长时间无响应导致 rsync 挂住 rsync -avz --timeout=60 --progress \ p24006111_112040_Linux-x86-64.zip \ oracle@10.0.0.11:/u01/patches/-a在这里不是简单等同于递归,它同时保留文件权限、时间戳、属主信息,保证补丁包在目标机的属性与源端一致,避免后续因为权限问题踩 4.4 节的坑。--timeout参数容易被忽略,但内网机器数量多时,某台机器负载高会导致 rsync 假死,没有超时限制,整个分发流程会被一台机器拖住,排查起来非常难受。
6.2 批量 md5sum 校验脚本:串行还是并行
分发完成后,不要立刻解压。写一个循环脚本,把所有目标机的 MD5 值拉回来统一比对:
#!/bin/bash # 标准值来自官方 CHECKSUM 文件 std_md5="9a2f7c1b7e4d5a8f6c0d1e2f3a4b5c6d" # 逐台机器取 md5,输出 OK/FAIL for host in db01 db02 db03; do rmd5=$(ssh $host "md5sum /u01/patches/p24006111_112040_Linux-x86-64.zip" | awk '{print $1}') if [ "$rmd5" = "$std_md5" ]; then echo "$host OK" else echo "$host FAIL" fi done这个脚本按顺序串行跑,胜在输出整齐、结果一目了然。机器数量超过十台时,可以考虑用&把 ssh 放到后台并行,但要注意:并行会让所有目标机同时打补丁,如果补丁涉及停实例和重启,业务影响会被放大。我的习惯是校验可以并行,真正执行 opatch 必须串行或分批,一次只动一台。补丁这种操作,保守永远是性价比最高的策略。
6.3 opatch rollback 的时机:后悔药也有保质期
最后说回滚。opatch apply之后如果发现补丁在生产环境引发问题,在 README 承诺支持 rollback 的前提下,可以用一条命令回滚:
# 回滚补丁,-id 指定补丁号,-oh 指定 ORACLE_HOME $ORACLE_HOME/OPatch/opatch rollback -id 24006111 -oh $ORACLE_HOME回滚和安装一样,需要先停监听、停实例,流程完全对称。有两个时机类问题要特别留意:第一,不要在打完新补丁之后才考虑回滚旧补丁,因为补丁之间可能存在覆盖和依赖关系,先回滚旧的往往把新的也破坏了。第二,如果已经用opatch auto或者-force等方式强制应用过补丁,回滚命令很可能失败,所以安装时就要为回滚留下干净的状态。
我的个人习惯是:补丁包落地后,第一件事永远是先跑一遍 md5sum 和 unzip -t,再谈安装。这两个命令加起来不到十秒,却能把后续所有排错时间砍掉大半。补丁这个东西,越怕麻烦越会碰到麻烦,把校验做成肌肉记忆,比任何所谓的经验都可靠。希望帮到你。
本文还有配套的精品资源,点击获取