
做Oracle运维这么多年我最常被问的问题之一就是“我这套11g单库到底要不要打PSU打补丁会不会出幺蛾子”说实话11g虽然“上了年纪”但在现在的生产环境里存量依然很大很多企业的核心业务库还跑在11.2.0.4上面。但官方对11g的普通支持早已结束真正还在持续发布的安全补丁主要就是PSU。这也让“Oracle 11g单库环境PSU补丁安装”成了每个DBA绕不开的日常操作。这篇文章我按自己实际打补丁的流程来写覆盖从补丁选型、环境准备、opatch apply、catbundle.sql数据字典更新到验证和回滚的完整过程。不管你是有几年经验的老DBA还是刚开始接触Oracle的运维新人按这个流程走一遍至少能少踩一半的坑。1. PSU补丁的核心思路与整体拆解1.1 为什么Oracle 11g必须打PSU补丁先说清楚PSU到底是什么。PSU的全称是Patch Set Update可以理解成Oracle在版本发布之后把一段时间内累积的修复统一打包成的一个补丁集合。它和单补丁One-off Patch最大的区别是PSU是累积式的也就是说新PSU包含了旧的PSU里所有的修复项。这意味着补丁不是越打越多而是越来越完整。你可以把PSU想象成一个不断更新的手机系统版本每次发布新版都会包含之前所有修复内容。Oracle 11.2.0.4是11g最后一个基础版本之后的补丁维护基本都靠PSU。以11.2.0.4为例PSU的编号规则一般是“11.2.0.4.年份日期”比如11.2.0.4.180717代表2018年7月发布。越新的PSU修复的安全漏洞和bug就越多。到了今天很多安全扫描工具检查出来的数据库漏洞官方给的建议基本都是“升级到最新的PSU”。所以打PSU不只是常规维护很多时候是安全整改的硬性要求。打PSU还有一个现实层面的原因如果你不维护补丁后面想恢复数据、排查疑难bugOracle支持很可能直接要求你先打个最新PSU再说。与其到时候仓促补不如平时就把补丁策略固定下来选一个维护窗口定期安装。1.2 单库环境打补丁的整体思路单库环境说到底就是一台服务器上跑一个数据库实例常见的部署形态是“单机本地文件系统”或“单机ASM存储”。相比RAC集群环境单库打PSU有个非常明显的优势不需要考虑滚动更新不需要跨节点协调只要规划好停机窗口一台一台处理就行。但单库环境也有自己的麻烦。因为只有一套环境一旦补丁打挂了整个业务都会直接停摆。所以单库打补丁的核心思路不是“快”而是“稳”。整个流程我一般拆成四个阶段准备、备份、执行、验证。准备阶段搞清楚当前版本和补丁包是否匹配备份阶段把数据库和关键配置文件都留好后路执行阶段按顺序来不跳步验证阶段不只是看补丁装没装上还要确认数据库运行状态、监听、日常业务是否正常。另外打补丁的窗口选择也很重要。哪怕是单库我也不会在业务高峰期动它。一般建议选择维护窗口提前通知业务方这个时间点足够你执行补丁、跑SQL脚本、做基础验证。时间不够的话宁可下次再打也不要赶工。1.3 先分清几个容易混淆的概念在动手之前有几个概念必须先搞清楚不然很容易在查阅资料时迷迷糊糊PSUPatch Set Update累积型补丁集合包含常规bug修复和安全修复每季度发布一次。CPUCritical Patch UpdateOracle早期对安全补丁的叫法现在已经统一到PSU里。SPUSecurity Patch Update有些平台或版本里Oracle会把只包含安全修复的补丁包单独命名为SPU作用类似但不完全等同。One-off Patch单个问题补丁只针对某个bug安装前最好经过Oracle支持确认。Bundle Patch主要用于Windows平台的累积补丁包Linux上不太提这个。实际工作中生产环境最常用的就是PSU。选补丁包的时候一定要注意匹配操作系统平台。同一个PSU编号Linux、Solaris、AIX、Windows的补丁包是完全不同的下载错了到了安装阶段才发现白白浪费时间和窗口。2. 补丁安装前的准备工作与检查项2.1 环境信息收集先搞清楚自己站在哪里打补丁之前第一件事不是下载补丁而是把当前环境信息摸清楚。我一般会整理一个信息清单至少包含以下几项操作系统版本和架构比如Red Hat Enterprise Linux 7.9 x86_64数据库版本和补丁基线比如Oracle 11.2.0.4.0还是已经打过某个PSU数据库实例的ORACLE_HOME路径、ORACLE_SID当前OPatch工具版本数据库是否启用了Data Guard、GoldenGate等同步机制数据库的大小、备份策略是否完好listener.ora、tnsnames.ora等关键配置文件的路径其中数据库版本这一步尤其关键。很多人以为自己装的是11.2.0.4实际上可能只是11.2.0.1或者已经打过了某个月的PSU再直接打最新PSU时就会遇到冲突。要确认当前版本最直接的方式就是用SQL查看select * from v$version;或者看补丁信息opatch lsinventoryopatch lsinventory这命令建议每次操作前都跑一遍它会把ORACLE_HOME下已经装过的补丁全部列出来你能清楚地看到当前基线是干净的裸版本还是已经带了很多历史补丁。这在后面做冲突检测时特别重要。2.2 OPatch工具的版本升级很多人忽略OPatch本身的版本等opatch apply报错才回头查其实这条写在最前面就能避免大部分问题。Oracle补丁包一般会要求OPatch的最低版本尤其是新出的PSU对OPatch版本要求会越来越高。11.2.0.4时代OPatch版本如果太低大概率会报“OPatch version is too low to support this patch”之类的错误。OPatch工具本身也是一个补丁包专门的补丁号通常是p6880880同样按平台区分。升级OPatch很简单先备份原来的OPatch目录然后把新版本解压覆盖到ORACLE_HOME/OPatch下。注意操作的执行用户必须是ORACLE_HOME的属主生产环境一般是oracle用户不能用root直接解压覆盖否则后续可能遇到权限错乱的问题。做完之后用以下命令验证版本opatch version我习惯把这一步放在所有准备工作最开始确认OPatch版本没问题后面的流程才会顺畅。版本号以Oracle官方文档里对应补丁的README要求为准不要自己拍脑袋判断。2.3 备份是底线补丁安装前必须做好的功课单库环境打补丁最大的恐惧不是补丁本身而是万一出问题之后没有后路。我见过不少案例数据库补丁打到一半opatch报错结果发现连备份都是旧的最后只能硬着头皮恢复过程极其痛苦。所以在打补丁之前备份这道工序绝对不能省。最低限度的备份要求是数据库逻辑备份或物理备份确认备份文件完整可恢复。备份ORACLE_HOME下的关键配置文件listener.ora、tnsnames.ora、sqlnet.ora、init.ora或spfile。记录当前的补丁列表和数据库版本信息方便回滚时对比。如果是生产库我还会额外做一次归档日志的检查确认归档目录没有异常堆积数据文件没有offline状态。这些检查看着琐碎但能提前发现一些潜在风险。比如之前遇到过一次数据库文件状态有问题打补丁本身没失败但后续启动实例时迟迟起不来查了半天才发现历史遗留问题。备份ORACLE_HOME配置我的做法是单独建一个备份目录用tar打包压缩再复制到另一台机器或异地目录。不要把备份文件放在ORACLE_HOME内部因为后续万一需要恢复整个目录放在里面可能会被覆盖。2.4 补丁包准备与冲突预检下载补丁包之后解压到临时目录目录路径尽量不要包含中文字符和空格也不建议放在ORACLE_HOME目录下。解压后先读一下补丁包自带的README尤其是补丁的安装要求和注意事项。README里通常会明确写出OPatch最低版本、是否需要额外操作、是否有已知问题等这些信息在Oracle官方文档里也有但直接看README最直观。解压完成后进入补丁目录做冲突检测和空间检查命令如下cd /tmp/patch/31537677 opatch prereq CheckConflictAgainstOHWithDetail -phBaseDir ./ opatch prereq CheckSystemSpace -phBaseDir ./第一条是检查新补丁和当前ORACLE_HOME已有的补丁是否冲突第二条是检查临时目录和ORACLE_HOME所在文件系统的剩余空间是否足够。这两个预检查是必做的尤其要注意第一个。如果检测出来有冲突必须先把冲突解决掉比如先回滚旧补丁或者向Oracle支持确认是否需要合并不能强行apply。实际操作中补丁包很大解压过程也可能遇到权限问题。建议解压完成后先看文件权限确认补丁目录下文件的属主是oracle而不是root。如果权限不对后续opatch apply依然会报错。3. 实操总结PSU补丁安装全流程3.1 关闭实例与监听保持环境干净安装PSU过程中最关键的一个操作是关闭数据库实例和监听。这一步在官方文档里写得很清楚但实际执行时经常有人偷懒只停实例不停监听或者干脆什么停不停直接跑opatch。结果就是二进制文件被进程占用opatch apply时报文件占用错误或者更隐蔽的是补丁装了一部分但进程还在用旧代码导致后续行为不可控。关闭实例之前我习惯先检查一下当前是否有活动的会话或长事务select count(*) from v$session;然后执行优雅关闭建议用normal或者transactional方式这样可以等事务完成后再关闭。如果时间紧可以先检查完会话再shutdown immediate一般业务库在维护窗口这样做问题不大。关闭监听用lsnrctl stop如果有EM Database Control或Oracle Agent在运行也一并停掉。11g单库环境常见的是dbconsole命令是emctl stop dbconsole如果数据库文件放在ASM里而ASM实例和数据库共用同一个ORACLE_HOME我也建议把ASM实例一并停掉避免$ORACLE_HOME/bin/oracle这个二进制文件被ASM进程占用。这一步不是所有环境都必须但在单库ASM组合下这样做更稳妥。关闭完毕之后确认一次ps -ef | grep ora_ | grep -v grep lsnrctl status看到没有监听进程、没有实例进程残留再进入下一步。3.2 opatch apply核心安装过程环境停干净之后正式进入安装。执行安装的用户必须是oracle用户命令顺序是cd $ORACLE_HOME export PATH$ORACLE_HOME/OPatch:$PATH cd /tmp/patch/31537677 opatch applyopatch apply的过程中会做一系列自检包括再次检查冲突、空间、补丁兼容性等。如果之前预检都通过这里一般能顺利走完。看到屏幕输出OPatch succeeded就表示二进制补丁已经打上了。这里有一个细节值得注意opatch apply执行过程中如果输出信息太长建议保留一份日志或者至少把输出重定向到文件里方便回查。有些老版本的opatch如果不指定日志会直接在屏幕上输出大量信息一屏滚过去后面想确认结果反而麻烦。打完补丁之后不要急着启动数据库。先检查一下二进制文件的属主和权限确认$ORACLE_HOME/bin/oracle还属于oracle用户并且权限正常。曾经遇过一次因为是root跑了一部分操作导致oracle二进制属主变成了root启动实例时报权限错误花了不少时间才排查清楚。3.3 执行catbundle.sql更新数据字典这是PSU安装流程中最容易被忽略的一步。二进制补丁更新的是Oracle程序文件但数据库里的数据字典内容还需要单独执行SQL脚本来更新。这一步不执行补丁相当于只装了一半后续很多功能可能表现异常。启动数据库到open状态后用SYS用户执行sqlplus / as sysdba SQL startup; SQL alter session set containerCDB$ROOT; SQL spool /tmp/catbundle_psu.log SQL ?/rdbms/admin/catbundle.sql PSU apply SQL spool off;注意11g还没有CDB概念所以不需要alter session set container直接执行catbundle.sql即可。正确格式是SQL $ORACLE_HOME/rdbms/admin/catbundle.sql PSU applyspool要把日志留下来方便最后检查是否报错。整个脚本跑的时间不固定短的十几分钟长的可能半小时以上具体取决于数据字典的大小和服务器性能。运行期间不要开其他会话去动数据库尤其不要执行DDL操作否则可能导致锁冲突。脚本跑完之后查看日志确认没有出现ORA-错误。catbundle.sql正常执行的结尾一般会提示类似Catbundle completed的信息。如果日志里有错误先不要慌把错误信息记录下来确认是致命错误还是可以忽略的告警。拿不准的情况下最好找Oracle支持确认不要贸然重跑。3.4 安装后的验证清单补丁打完了数据字典更新也完成了但整个安装流程还没结束至少要做一轮基础验证。我习惯按下面这个清单过一遍查询当前补丁列表opatch lsinventory或者只看补丁IDopatch lspatches确认要安装的PSU编号在列同时查看数据字典里的SQL patch记录select * from dba_registry_sqlpatch;在这条记录里能看到ACTION列是APPLYSTATUS列是SUCCESS这表示SQL patch已经正确应用。接下来验证数据库运行状态。执行select open_mode from v$database; select status from v$instance;然后启动监听lsnrctl start lsnrctl status主要确认监听进程起来了数据库实例能正常注册到监听。这一步非常关键因为单库环境如果监听起不来对业务的影响和数据库宕机没什么区别。最后做一次最小化的业务验证比如通过JDBC连接串连接一次会话执行一条简单的查询语句确认网络连接正常最基本的功能没坏。这一步看似多余但在实战中能快速发现一些隐藏问题比如JDBC驱动和补丁后的数据库不兼容之类的早发现早解决。4. 常见问题排查与避坑指南4.1 opatch apply时报错空间不足、权限错乱怎么办opatch apply最常见的报错之一是文件系统空间不足。虽然前面预检时做了CheckSystemSpace但有些环境在补丁执行期间日志文件、回滚文件会持续写入临时目录可能突然被占满。遇到这种情况先看哪个目录满了用df -h确认然后清理临时文件和旧日志再重新执行opatch apply。opatch apply本身具备续跑能力吗严格来说Oracle的opatch在失败后不会从断点继续而是需要清理现场后再重试。重试前要检查ORACLE_HOME/bin目录下有没有残留的备份文件比如.copy或.orig结尾的文件。如果有说明上一次安装的中间状态还没清理干净需要修复或还原后重新再来。权限方面最常见的错误是“Permission denied”。原因基本就是前面提到的用了root用户执行了某些步骤导致ORACLE_HOME下文件的属主变了。遇到这种情况不要直接在root下改权限然后继续而是要用oracle用户对变更的文件做属主修复或者从备份里恢复受影响文件。如果是root跑opatch导致的损坏更保险的方案是找一台同版本的测试机重新校验一遍。4.2 如果补丁安装失败如何回滚打完补丁后发现异常需要回滚时分两种情况二进制补丁已经apply但SQL脚本还没执行或者SQL脚本也执行了。如果SQL脚本还没执行回滚就相对简单。进入补丁目录用OPatch自带的方式回滚cd /tmp/patch/31537677 opatch rollback -id 31537677 -phBaseDir ./rollback之后再重新启动数据库到open状态确认一切正常即可。如果opatch报错说不支持rollback那就只能从备份恢复ORACLE_HOME这种场景比较少但也不是没有。如果SQL脚本已经执行情况就复杂了。此时数据字典已经变化单纯回滚二进制补丁会导致二进制和字典版本不匹配数据库反而更容易出问题。稳妥的路线是从备份完整恢复数据库回到打补丁之前的某个时间点。这也是为什么我在前面反复强调备份的重要性。没有备份硬着头皮处理往往耗时更长、风险也更高。还有一种少见情况PSU应用失败但日志里没有明显报错数据库也能起来只是某些功能不正常。这种情况我建议先用dba_registry_sqlpatch确认SQL patch的实际状态再根据具体症状对log进行排查必要的时候再咨询Oracle支持。4.3 打补丁后监听服务无法启动的排查思路热词里经常有人搜“oracle监听服务无法启动”打完补丁后遇到这个问题的概率确实不低。监听启动失败的原因很多但在补丁场景下最常见的就是这几种listener.ora被修改或损坏。ORACLE_HOME环境变量没有切换到补丁更新后的路径。端口被占用。文件权限不对监听进程没有权限读取配置。排查顺序我一般从简单到复杂先看监听配置文件内容确认监听端口、协议、主机名有没有异常再用命令启动并观察报错具体信息lsnrctl start lsnrctl status如果是端口被占用用netstat -anp | grep 1521确认杀掉占用进程或者修改监听端口。如果监听配置没问题那就检查环境变量确认当前shell里的ORACLE_HOME和PATH指向的是补丁更新后的正确路径。有时候打完补丁用户登录时的环境变量文件比如.bash_profile里还残留了旧路径导致监听进程加载了旧配置。实际运维中我遇到最多的其实是懒省事的做法——用root直接启动监听导致监听进程以root身份运行后续oracle用户登录之后反而看不到监听状态。正确的操作方式应该是su - oracle之后再执行lsnrctl保证权限归属清晰。4.4 打PSU期间容易忽略的几个细节最后分享几条实战中的个人习惯虽然算不上什么高深技术但踩过坑之后就知道这些细节多值钱。第一补丁目录最好保留到下一次补丁打完再删。不仅是方便回滚也是方便对照检查。第二打补丁当天不要执行任何其他变更操作。比如不要同时去改数据库参数、调整表空间、删归档日志。补丁过程本来就够复杂变量越少越好这算是我做变更管理的一条铁律。第三安装完成后跟业务方确认一下关键交易或存储过程是否正常。热词里经常有人搜“oracle存储过程”相关问题有些存储过程在补丁后因为SQL执行计划变化突然变慢或者出现奇怪的报错。这种问题不一定是补丁本身写坏了更多时候是优化器行为变化造成的。遇到这类情况先从执行计划入手排查不要急着回滚。补丁维护这件事说白了就一句话理性重视按流程走。每一步都做到位数据库和业务都会很平稳跳过任何一个小步骤都可能在某一天变成生产事故。希望这份实操记录能帮你顺顺利利完成一次Oracle 11g单库PSU补丁安装。