ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Windows 平台 Oracle 19c 补丁升级与 opatch 实战

Windows 平台 Oracle 19c 补丁升级与 opatch 实战 Windows 上给 Oracle 19c 打补丁真正难住人的从来不是命令本身——opatch apply加datapatch这两条背下来用不了一分钟。真正让人在机房里熬到后半夜的是 Windows 那套文件锁、服务依赖、杀毒软件扫描的组合拳是opatch跑到一半来个 OPatch failed with error code 73是你明明停干净了服务oracle.exe还赖在内存里不走。这篇就把我从 19.x 一路打上来踩过的坑、验证过的顺序、以及几个能省半小时的野路子完整摊开讲一遍适用于单机 CDB 架构的 19c 生产库或测试库升级。1. Windows 平台给 19c 打补丁难点根本不在命令本身很多人第一次在 Windows 上做 Oracle 19c 补丁升级会下意识套用 Linux 的经验——解压、opatch apply、datapatch三条命令走完收工。真上手才发现Linux 上顺风顺水的流程到 Windows 这边会多出来好几道莫名其妙的门槛而且每一道门槛的报错信息都含糊得让人想砸键盘。1.1 文件锁、服务依赖和杀软Windows 特有的三道坎先说文件锁。Oracle 在 Windows 上运行的时候ORACLE_HOME\bin目录下的一堆 DLL、oracle.exe、tnslsnr.exe都会被操作系统独占加锁。只要你还有任何一个 Oracle 进程挂在那儿opatch在替换文件时就会直接失败。这跟 Linux 上进程没了文件句柄就释放的逻辑不太一样Windows 上经常出现服务停了、任务管理器里进程还在的尴尬局面。再说服务依赖。Windows 上 Oracle 是通过OracleServiceSID这个服务拉起实例的监听是另一个独立服务OracleOraDB19Home1TNSListener。你停服务的时候如果只停了一个另一个会拖着你。更麻烦的是有些第三方监控软件、备份代理、定时任务会在你停机之后自动把服务拉起来opatch跑到一半突然发现文件被占用前面的活儿全白干。第三道坎是杀毒软件和 Windows Defender。opatch apply要往 Home 里写几万个文件实时保护会挨个扫一遍本来二十分钟的活儿能给你拖到一个半小时。我在一台装了某国产终端防护的服务器上实测过关掉实时扫描之后apply时间从 78 分钟降到 19 分钟差距就是这么夸张。提示动手前先把ORACLE_HOME目录加进杀软的排除列表打完补丁再恢复。这一步不写入任何官方文档但能实打实救你的时间。所以我的习惯是每次打补丁前先在纸上列一份停机清单哪些服务要停、哪些定时任务要暂停、哪些监控要临时关掉。清单本身就是经验照做能避开八成的中间报错。1.2 搞清楚补丁类型再谈升级路径Oracle 19c 的补丁体系看着乱捋清楚其实就几类理解它们的区别决定了你能不能一步到位。补丁类型全称说明是否累积RURelease Update季度发布含安全修复和功能修复是可直接跳最新RURRelease Update Revision月度修订只含安全修复是OJVMOracle JavaVM 补丁单独发布修复 JVM 层问题独立轨道One-off单点补丁针对特定 Bug否需按依赖顺序关键点在于19c 的 RU 是累积的也就是说你从 19.3 的基础版本理论上可以一步打到 19.25不需要一级一级往上爬。但这里有个前提——你的OPatch版本必须够新而且 OJVM 补丁得单独拎出来处理。OJVM 那条线是独立的它有同一 Home 上连续 apply/rollback 有次数上限的限制踩爆了就得重装 Home所以打之前先opatch lspatches看看当前 OJVM 装到哪一版。我一般的做法是RU 和 OJVM 分开两个窗口处理先 RU 后 OJVM中间用一次datapatch把 SQL 层面的活干完再单独处理 OJVM 的 SQL 部分。这个顺序在多次实操里最稳不容易出岔子。2. 升级前的准备把该查的版本、该留的备份全做掉补丁这东西准备阶段花的时间越多执行阶段翻车的概率越低。我见过太多人上来就解压开干结果打到一半发现 OPatch 版本不够回退又不会整个人僵在那儿。2.1 读懂 19.25.0.0.241015 这串版本号以当前较新的补丁19.25.0.0.241015为例这串数字不是随便编的。19.25表示这是 19c 的第 25 个 Release Update对应 2024 年 10 月发布尾缀241015是版本日期字符串读作 24 年 10 月 15 日。你以后看到19.24.0.0.240716这种也照这个规律拆——前面是 RU 序号后面是年月日。搞清楚这个有什么用一是下补丁包的时候不会拿错二是跟同事沟通的时候能一句话说清我们现在在哪个版本。顺手记一下查看当前版本的两条命令sqlplus -v或者在数据库里查select banner_full from v$version;前者告诉你客户端和工具链版本后者告诉你数据库实际运行的版本。补丁升级完这两个不一定同步变化别看到sqlplus -v没变就以为没打上。补丁包解压这一步也有讲究。Windows 自带解压工具处理长路径时容易丢文件我建议用 7-Zip并且把补丁解压到一个浅目录比如D:\patch\19.25。原因是 Oracle Home 本身的路径已经很长了补丁里的文件路径再层层嵌套很容易撞上 Windows 260 字符的路径上限报出一堆莫名其妙的找不到文件。解压完检查一下目录里有没有README.html这是你后面所有操作的唯一权威说明。2.2 OPatch 版本自检与冲突预检OPatch是补丁的搬运工版本不够新它会直接拒绝干活。19.2x 系列的 RU 普遍要求OPatch 12.2.0.1.36以上而像 19.24、19.25 这类较新的补丁README 里会点名要12.2.0.1.40以上。具体以补丁包里的README.html为准我这里给的只是大致规律。查当前版本cd %ORACLE_HOME%\OPatch opatch version如果版本不够直接把新 OPatch 解压覆盖到ORACLE_HOME\OPatch目录就行——覆盖前先把旧目录整个备份一份这样出问题能退回去。覆盖之后记得再opatch version确认一遍。版本对了接下来做冲突预检。这一步很多人跳过我认为是补丁流程里最不该省的一步opatch prereq CheckConflictAgainstOHWithDetail -ph D:\patch\19.25\12345678把补丁号换成你实际解压出来的那个目录名。这条命令会扫一遍当前 Home 里已有的补丁看有没有跟新补丁冲突的。输出里如果出现Conflict字样别急着往下走先看冲突的是哪个补丁号再翻 README 看是否需要先把它 rollback 掉。我遇到过一次冲突是因为上一轮打的一个 one-off 补丁没清理预检直接拦下来省了我一次回滚重来的功夫。2.3 备份策略RMAN 之外还要留住 Oracle Home 的原貌数据库层面的备份常规做法是打补丁前做一次全备加归档备份。这个不用我多说RMAN跑一遍就行。但 Windows 上打补丁光有数据库备份还不够你得给ORACLE_HOME本身留一份还原点。原因很简单opatch apply改的是 Home 里的二进制文件如果中途失败或者打完之后发现有兼容问题数据库备份是救不了 Home 的。我的做法是打补丁前把整个ORACLE_HOME目录复制一份到别处或者用系统自带的卷影副本做个快照。Home 目录通常几个 G 到十几个 G多花二十分钟复制换来的是彻底玩崩了也能整个换回去的底气。除了文件还有几样东西要一起留ORACLE_HOME\OPatch\oraInst.loc里面记录了 Home 的注册信息重装或修复时要用。ORACLE_HOME\inventory目录OPatch 的补丁清单就在这里丢了会导致lsinventory读不出来。服务配置services.msc里把 Oracle 相关服务的启动类型截个图回滚的时候能对照恢复。TNS_ADMIN下的监听配置listener.ora、tnsnames.ora复制一份虽然后期不太会动但留着踏实。这些东西凑齐你才算真正有了后路。3. 停服务与清进程让 opatch apply 能顺利跑完的关键十分钟准备工作做完进入实操阶段。这一阶段最容易出问题的不是命令执行而是我以为停干净了的自欺欺人。3.1 服务停机顺序与残留 oracle.exe 的清理正确的停机顺序是先停数据库相关服务再停监听服务最后确认所有 Oracle 进程都退干净。顺序反了会怎样如果先停监听某些客户端连接会报错并触发重连反而让实例忙起来停服务耗时变长。停服务可以在服务管理器里点也可以命令行net stop OracleServiceORCL net stop OracleOraDB19Home1TNSListener服务名里的ORCL换成你自己的实例名。停完之后别急着往下走用这条命令把所有还挂着的 Oracle 进程揪出来tasklist | findstr /i oracle正常情况下应该什么都查不到。如果还看到oracle.exe或tnslsnr.exe说明有残留opatch一定会失败。这时候要么用taskkill /f /im oracle.exe强杀要么去服务里看看是不是有别的实例服务没停。这里有个特别隐蔽的坑如果你的 Windows 上装了不止一个 Oracle Home或者有 Oracle 的其它组件比如某些客户端、代理、监控采集器它们可能也调用同一个 Home 下的文件。我碰到过一次折腾半天发现是某个自研的数据同步小程序在后台连着库杀了它才停干净。所以打补丁前最好把所有可能连到这个 Home 的非必要程序都关掉包括你自己开的 SQL 工具。还有一类东西容易被忽略Windows 的计划任务。有些环境配了定时备份、定时统计的任务你停机的窗口里它正好触发把服务又拉起来。动手前花两分钟翻一遍任务计划程序把跟这个库相关的全禁用打完再启用。3.2 opatch apply 的输出解读与卡顿处理一切就绪用管理员权限开一个cmd切到ORACLE_HOME\OPatch目录开打cd %ORACLE_HOME%\OPatch opatch apply -ph D:\patch\19.25\12345678-ph指向解压出来的补丁目录。如果 README 里要求 OJVM 特殊处理那就得按它说的加参数。执行过程中屏幕上会滚动一堆Applying patch ...的信息。这里要注意opatch开场的那段自检输出。它会先列一遍检查项Oracle Home 状态、正在运行的进程、补丁目录校验、空间检查。只要有任意一项是Failed它会直接退出不会往下走。所以看到开头报错先别怀疑补丁包坏了八成是前面哪一步没做干净。apply跑到一半卡住不动是我在 Windows 上遇到最多的情况。原因通常有两个一是杀软在扫描某一个刚写进去的文件二是资源管理器之类的程序打开了 Home 下的某个目录触发了文件锁。处理办法很简单——别乱按键盘也别关窗口等一两分钟多数情况下它自己会继续。真卡死超过五分钟那就说明确实被占住了只能CtrlC中断清理进程后重来。中断之后可能有部分文件已经写入这时候先用opatch rollback试着退掉退不干净就上备份恢复。补丁打完opatch会输出一行OPatch succeeded。看到这行才算真的成功没看到就当它失败。顺手验证一下opatch lspatches命令会列出 Home 里当前所有已安装的补丁号和描述确认你打的这个19.25出现在列表里。4. datapatch补丁真正落到数据字典的那一步到这儿很多人以为补丁打完了。其实opatch apply只更新了 Home 里的二进制文件数据库内部的数据字典、组件版本、SQL 脚本执行状态一样都没动。差的那一步就是datapatch。4.1 为什么 apply 成功不等于补丁生效简单说opatch apply干的是换零件的活——把新版本的执行文件、库文件、脚本文件铺到磁盘上。但数据库内部还维持着旧版本的状态比如dba_registry里记录的组件版本、registry$sqlpatch里的补丁元数据这些都是要向数据库注册新补丁才会更新的。datapatch就是负责这个注册动作的。它会根据 Home 里的补丁清单连到数据库上逐个执行对应的 SQL 升级脚本把数据字典、PL/SQL 包、视图定义全部刷一遍。所以你打完之后查v$version看到版本号变了但组件状态还是旧的就是漏了这一步。这一步还有个副作用要注意datapatch执行期间数据库是处于变更状态的不能中断中断了可能留下半成品状态处理起来很麻烦。所以做之前确保CDB 根和所有 PDB 都处于OPEN状态。有足够的归档空间datapatch会产生不少归档。没有别的 DDL 在跑避免跟补丁脚本撞车。启动数据库的时候别用startup upgrade直接用普通启动到OPEN就行datapatch自己知道该提升什么状态。4.2 datapatch -verbose 的执行细节与多 PDB 处理执行命令仍然在ORACLE_HOME\OPatch目录下cd %ORACLE_HOME%\OPatch datapatch -verbose-verbose是必须加的它会实时输出每个补丁脚本的执行状态出问题时能一眼定位到是哪个脚本挂了。不加这个参数的话它只给你一个成功或失败出错了得重新跑一次才知道细节。19c 默认是 CDB 架构datapatch会自动识别所有 PDB 并逐个处理包括PDB$SEED。执行过程中你会看到类似这样的输出Analyzing patches for all PDBs Applying patches for PDB$SEED Applying patches for ORCLPDB1如果某个 PDB 没打开它会跳过并给出提示。这种情况下处理办法是把该 PDB 打开再单独跑一次datapatch或者用-pdbs参数指定目标datapatch -verbose -pdbs ORCLPDB1多 PDB 环境里我习惯在跑之前先确认所有 PDB 的状态select name, open_mode from v$pdbs;全部READ WRITE才开跑。跑完之后datapatch会输出一个总结段列出每个补丁在每个 PDB 上的执行结果看到全是SUCCESS才算完。整个过程视 PDB 数量和补丁大小从几分钟到半小时不等。5. 打崩了怎么退回滚链路与补丁后的自检打补丁失败是常事关键是知道怎么退。Oracle 给的退路其实挺完整只是要按顺序来顺序错了会退不干净。5.1 opatch rollback 与 datapatch -rollback 的配合顺序回滚的原则跟打补丁是完全对称的先退 SQL 层面的再退文件层面的。第一步在数据库里退 SQL 补丁datapatch -verbose -rollback patch_id这里的补丁号是19.25.0.0.241015这种形式不是那几个数字。退之前确认数据库处于OPEN状态所有 PDB 都是READ WRITE。这一步会把数据字典改回旧版本执行完之后数据库就不认识这个新补丁了。第二步在 Home 层面退文件opatch rollback -id patch_numberpatch_number是那串纯数字的补丁编号比如12345678。执行前同样要停掉所有服务和进程跟apply时的要求一样。这个顺序不能反。如果你先 rollback 文件再想 rollback SQL会发现datapatch找不到对应的补丁脚本了数据库就会卡在一个文件和字典不匹配的危险状态处理起来相当难受。还有一种情况是apply中途失败了Home 已经是半新半旧的状态。这时候可以试着rollback如果 OPatch 报错说找不到完整补丁信息那就只能动用之前备份的ORACLE_HOME整个覆盖恢复。这也是我前面强调备份 Home 的原因。5.2 补丁后必查项与高频报错排查表补丁顺利打完别急着宣布结束跑一轮自检select patch_id, action, status, action_time from dba_registry_sqlpatch order by action_time desc;这条查出来的是补丁的注册记录ACTION是APPLY、STATUS是SUCCESS才算数。多 PDB 环境里dba_registry_sqlpatch在 CDB 根里会带CON_ID列能看到每个 PDB 的记录。补丁版本多的时候PATCH_ID列会给出这次打的编号跟opatch lspatches的输出对照一下。再查一遍组件状态select comp_name, version, status from dba_registry where status VALID;这条应该返回空。如果有组件状态异常通常跑一次utlrp.sql重编译无效对象就行?/rdbms/admin/utlrp.sql下面这张表是我这些年攒下来的高频报错按场景对号入座报错信息常见原因处理方式OPatch failed with error code 73Home 下有进程或文件被占用停服务、tasklist清进程、关杀软后重试OPatch failed with error code 239补丁目录路径错误或文件缺失检查-ph路径重新解压补丁包Prereq checkSystemSpace failed磁盘空间不足清理ORACLE_HOME所在盘留出补丁包 3 倍空间Prereq checkActiveFilesAndExecutables有oracle.exe在跑强制结束进程后opatch prereq复验datapatch 报 ORA-04061 / ORA-06512包状态不一致通常是中断残留重启实例后重跑datapatch -verbose某 PDB 在 sqlpatch 里查不到记录该 PDB 执行时未打开打开 PDB用-pdbs单独补跑这套自检加排错覆盖了我遇到过九成以上的异常。剩下那一成基本都是环境本身的特殊问题只能靠看日志。日志位置记住两个ORACLE_HOME\cfgtoollogs\opatch和ORACLE_BASE\cfgtoollogs\datapatch出问题先扒日志比在网上瞎搜快得多。最后分享一个我自己用的小技巧每次打完补丁把opatch lspatches的输出和dba_registry_sqlpatch的查询结果各存一份到文档里标注日期和补丁版本。下次打新补丁前翻出来对比能一眼看出上次打到哪、这次该从哪接团队交接的时候也是现成的记录。这个习惯听上去土但在需要频繁升级的环境里它比任何工具都靠谱。
返回列表