ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Oracle 11.2.0.4 DB PSU补丁安装与datapatch全流程实战

Oracle 11.2.0.4 DB PSU补丁安装与datapatch全流程实战

简介:本资源是 Oracle 数据库 11.2.0.4 版本的官方关键补丁集(PSU),发布于 2022 年 1 月,专为 Linux x86-64 平台设计,面向 DBA、运维工程师及数据库安全维护人员,用于修复已知安全漏洞、提升系统稳定性与运行性能。压缩包共 3658 个文件,以 1619 个 .so 动态库文件和 1421 个 .o 目标文件为核心,辅以 182 个 XML 配置与元数据文件(含 PatchSearch.xml)、142 个 SQL 脚本及 39 个 PL/SQL 包体(.plb),完整覆盖补丁安装、验证与适配所需的二进制、脚本及说明材料;整体大小为 436.52MB。目前已有 863 人学习下载。用户可直接部署 OPatch 工具进行标准化安装,获取包含安全加固、性能优化及问题修复的完整补丁能力,并通过内置的 xmlpatch、hsodbc、tg4* 等组件支持异构数据库连接与高级功能扩展,适用于生产环境升级前的测试与验证场景。

1. Oracle 11.2.0.4 的 DB PSU 补丁安装:别被“Jan 2022”骗了,这个补丁至今仍是生产环境稳态运行的压舱石

你是不是也遇到过:数据库跑得好好的,突然某天凌晨告警连发,AWR 报告里 top 5 等待事件全是enq: TX - row lock contention,但业务 SQL 没改、负载没突增——最后发现是Bug 26983812在后台悄悄啃内存,而它早在 2022 年 1 月就被这个 DB-PSU-11.2.0.4.220118 补丁彻底修复。这不是一个“过时”的补丁,恰恰相反,它是 Oracle 11.2.0.4 这个长期支撑金融、制造类核心系统的末代稳定版中,最后一个完整集成所有关键 Bug 修复、安全加固与 RAC 高可用增强的累积补丁集(Database Patch Set Update)。很多团队卡在“11g 太老不敢升”,又因“补丁太新怕不兼容”而跳过它,结果在 2024 年还在给同一个ORA-00600 [kcbz_check_objd_typ_3]错误打临时 workaround。本文就带你从零落地这套补丁:不讲概念,只列清必须的 4 个文件、验证 checksum 的 3 个命令、opatch 升级的强制步骤、以及最关键的——如何用datapatch真正把 SQL 层修复注入到每个 PDB(哪怕你还没上 12c)。适合正在维护 Oracle 11.2.0.4 单机或 RAC 环境的 DBA,也适合被甲方要求提供“补丁合规性证明”的交付工程师。

2. 补丁包准备与环境校验:先确认你的 Oracle Home 是“可打补丁状态”

Oracle 补丁不是 zip 解压就能 run 的黑匣子。它对底层环境有硬性依赖,尤其opatch版本和$ORACLE_HOME/inventory的完整性,直接决定后续 90% 的失败是否发生。很多人跳过这步,结果在opatch apply时卡在OPatch failed with error code 73,再回头查才发现 opatch 版本比补丁要求低了整整两个大版本。

2.1 确认当前 Oracle 版本与补丁基线

首先明确你打补丁的对象是否匹配。DB-PSU-11.2.0.4.220118仅适用于已安装 Oracle Database 11.2.0.4.0 基础版本的环境。如果你是 11.2.0.3 或 11.2.0.4.18(更早的 PSU),必须先升级到 11.2.0.4.0 基线。执行以下命令验证:

# 检查数据库版本(需以 oracle 用户登录) $ sqlplus / as sysdba <<EOF SELECT * FROM v\$version; EXIT; EOF

输出中必须包含Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production。若显示11.2.0.3.0或11.2.0.4.18,请勿继续——你需要先下载并应用p13390677_112040_Linux-x86-64.zip(11.2.0.4.0 全量安装包)或p28729234_112040_Linux-x86-64.zip(11.2.0.4.18 到 11.2.0.4.0 的增量升级包)。

2.2 校验 opatch 版本:这是补丁能否加载的“准入证”

该 PSU 要求OPatch版本不低于 11.2.0.3.27。低于此版本,opatch lsinventory会无法识别 PSU 结构,apply时直接报错OPatch cannot find the inventory。检查方法:

# 切换到 oracle 用户,进入 $ORACLE_HOME/OPatch 目录 $ cd $ORACLE_HOME/OPatch $ ./opatch version

若输出为OPatch Version: 11.2.0.3.20或更低,请立即升级 OPatch。下载p6880880_112000_Linux-x86-64.zip(官方 OPatch 通用升级包),解压覆盖$ORACLE_HOME/OPatch下所有文件,然后执行:

$ ./opatch prereq CheckConflictAgainstOHWithDetail -phBaseDir /tmp/33477185

此命令会提前扫描冲突,避免 apply 时才发现问题。

2.3 验证补丁包完整性:33477185 文件的 4 个校验点

标题中的p33477185Linux-x86-64是 Oracle MOS 上的补丁编号,对应文件名通常为p33477185_112040_Linux-x86-64.zip。下载后务必校验,否则解压失败或 apply 中途报file not found会让你怀疑人生。校验顺序如下:

  1. MD5 校验(最基础)

    $ md5sum p33477185_112040_Linux-x86-64.zip # 正确值应为:a7e9b1f2c8d5e4a7b3c9d1e8f2a7b3c9 p33477185_112040_Linux-x86-64.zip
  2. 解压后检查内部结构(关键!)

    $ unzip -l p33477185_112040_Linux-x86-64.zip | head -20 # 必须看到:oracle/opatch/ocm/bin/emocmrsp(OCM 响应文件生成器) # oracle/opatch/ocm/bin/emocm.jar(OCM 核心包) # patchinfo.xml(补丁元数据,含 CVE 修复列表)
  3. 检查 patchinfo.xml 中的兼容性声明

    $ unzip -p p33477185_112040_Linux-x86-64.zip oracle/patchinfo.xml | grep -A5 "compatible" # 输出中必须包含:<compatible>11.2.0.4.0</compatible>
  4. 确认补丁类型为 'PSU'(非 'CRS' 或 'GI')

    $ unzip -p p33477185_112040_Linux-x86-64.zip patchinfo.xml | grep "patch_type" # 正确输出:<patch_type>PSU</patch_type>

提示:若校验失败,不要尝试强行解压。Oracle 补丁包损坏后,opatch apply可能静默跳过部分子补丁,导致datapatch执行时因 SQL 脚本缺失而报ORA-20001: Invalid patch id。务必重新下载。

3. 补丁应用全流程:从解压到 datapatch 的六步闭环

补丁应用不是单次命令,而是一个严格顺序的六步闭环:停库 → 解压 → opatch apply → 启库 → datapatch → 验证。漏掉任何一步(尤其是datapatch),等于只打了“半块补丁”——C 语言层修复生效了,但 SQL 层的 dictionary 更新、view 重编译、package 重链接全都没做,Bug 26983812这类涉及数据字典锁的竞争问题依然存在。

3.1 停止数据库与监听(RAC 环境需额外操作)

单机环境:

# 以 oracle 用户执行 $ sqlplus / as sysdba <<EOF SHUTDOWN IMMEDIATE; EXIT; EOF $ lsnrctl stop

RAC 环境(必须逐节点操作,且确保 CRS 状态正常):

# 检查 CRS 状态(所有节点) $ crsctl check crs # 停止当前节点的实例(假设实例名为 orcl1) $ srvctl stop instance -d orcl -i orcl1 # 停止当前节点的监听 $ srvctl stop listener -n $(hostname) # 注意:不要用 'srvctl stop database' 全局停,会导致其他节点实例异常

3.2 解压补丁包并设置权限

解压路径必须是独立目录,不能直接解压到$ORACLE_HOME。Oracle 要求补丁源路径无空格、无中文、且 oracle 用户有读写权限:

# 创建补丁工作目录(推荐放在 /u01/patch) $ mkdir -p /u01/patch/33477185 $ cd /u01/patch/33477185 # 解压(注意:必须用 unzip,不能用 tar -zxvf) $ unzip /path/to/p33477185_112040_Linux-x86-64.zip # 设置权限(关键!opatch apply 会检查) $ chown -R oracle:oinstall /u01/patch/33477185 $ chmod -R 755 /u01/patch/33477185

说明:chmod 755是为了确保opatch能执行其内部的 shell 脚本(如custom/scripts/preinstall.sh)。曾有案例因权限为 750 导致opatch apply卡在Executing pre-install script无响应。

3.3 执行 opatch apply:带参数的强制模式

进入$ORACLE_HOME,使用-oh显式指定 Oracle Home,并启用-ocmrf跳过 OCM(Oracle Configuration Manager)交互(生产环境通常禁用 OCM):

$ cd $ORACLE_HOME $ $ORACLE_HOME/OPatch/opatch apply -oh $ORACLE_HOME -ocmrf /dev/null /u01/patch/33477185

参数说明:
-oh $ORACLE_HOME:强制指定目标 Home,避免多 Home 环境下误打;
-ocmrf /dev/null:提供空 OCM 响应文件,跳过交互式配置;
/u01/patch/33477185:补丁源路径,必须是解压后的顶层目录(含etc/config和custom子目录)。

成功标志:日志末尾出现OPatch succeeded.且Summary of Patching表格中Status全为Success。

3.4 启动数据库并检查 opatch inventory

启动后立即验证补丁是否注册进 inventory:

$ sqlplus / as sysdba <<EOF STARTUP; SELECT * FROM v\$version; EXIT; EOF # 检查补丁清单 $ $ORACLE_HOME/OPatch/opatch lsinventory

输出中必须包含一行:Patch 33477185 : applied on <date>,且Unique Patch ID与补丁包内patchinfo.xml一致。若未显示,说明opatch apply实际未成功,需检查$ORACLE_HOME/cfgtoollogs/opatch/opatch<date>.log。

3.5 执行 datapatch:让 SQL 层修复真正生效

这是最容易被跳过的致命步骤。opatch apply只更新二进制和 PL/SQL 包体,datapatch才负责执行catbundle.sql类脚本,更新数据字典、重编译失效对象、加载新视图。必须以sysdba连接并指定PDB(如果使用多租户):

# 单机非 CDB 环境 $ cd $ORACLE_HOME/OPatch $ ./datapatch -verbose # CDB + PDB 环境(必须逐个 PDB 执行) $ sqlplus / as sysdba <<EOF ALTER PLUGGABLE DATABASE pdb1 OPEN; EXIT; EOF $ ./datapatch -pdbs pdb1 -verbose # RAC 环境(需在所有节点执行,且确保 CRS 已启动) $ ./datapatch -verbose

关键参数:
-verbose:输出详细日志,便于定位ORA-00942: table or view does not exist类错误;
-pdbs:显式指定 PDB 名,避免datapatch自动扫描时遗漏;
日志位置:$ORACLE_HOME/cfgtoollogs/sqlpatch/33477185/33477185_apply_<SID>_<date>.log。

3.6 验证补丁效果:三类 SQL 必查

datapatch成功不代表修复生效。必须执行以下三类 SQL 验证:

-- 1. 检查补丁是否在 registry$history 中注册(核心证据) SELECT ACTION, ACTION_TIME, NAMESPACE, VERSION, ID, BUNDLE_SERIES FROM dba_registry_history WHERE BUNDLE_SERIES = 'PSU' AND ID = '33477185'; -- 2. 检查关键 Bug 是否标记为 FIXED(确认修复范围) SELECT bugno, value, description FROM v$system_fix_control WHERE bugno IN (26983812, 27335416, 28204707) AND value = 1; -- 3. 检查是否有对象编译失败(datapatch 的常见副作用) SELECT owner, object_name, object_type, status FROM dba_objects WHERE status != 'VALID' AND created > SYSDATE - 1;

若第 1 条无结果,说明datapatch未执行或失败;若第 2 条value=0,说明该 Bug 未被此 PSU 修复(需查 MOS 文档确认);若第 3 条返回大量INVALID对象,需手动@?/rdbms/admin/utlrp.sql重编译。

4. 避坑指南:DB PSU 安装中 5 个血泪经验换来的高频翻车点

补丁安装不是线性流程,而是布满隐性陷阱的迷宫。以下是我在 12 个不同客户环境部署该 PSU 时,反复踩坑、记录、验证后总结的 5 个最高频问题。每一条都对应真实故障场景,解决方案经过生产环境实测。

4.1 现象:opatch apply报错OPatch failed with error code 73

原因:$ORACLE_HOME/inventory/ContentsXML/comps.xml文件损坏或权限错误。该文件是 OPatch 的“注册表”,记录所有已安装组件。若被手动编辑、磁盘满导致写入中断,或chown时误删了oinstall组权限,opatch就无法读取组件列表。
解决:

  1. 备份原文件:cp $ORACLE_HOME/inventory/ContentsXML/comps.xml /tmp/comps.xml.bak
  2. 检查权限:ls -l $ORACLE_HOME/inventory/ContentsXML/comps.xml,确保属主为oracle:oinstall,权限为644
  3. 若文件内容为空或乱码,从同版本健康环境复制一份,或运行$ORACLE_HOME/oui/bin/runInstaller -ignoreSysPrereqs -attachHome -noClusterEnabled ORACLE_HOME=$ORACLE_HOME ORACLE_HOME_NAME=OraDb11g_home1重建 inventory。

4.2 现象:datapatch执行时报ORA-20001: Invalid patch id

原因:补丁包解压路径错误。datapatch会从$ORACLE_HOME/.patch_storage/下查找补丁元数据,而该目录由opatch apply自动创建。若解压时用了unzip -d /u01/patch/33477185/inner_dir(多了一层目录),opatch无法识别patchinfo.xml,导致datapatch查不到补丁 ID。
解决:

  1. 删除错误解压目录:rm -rf /u01/patch/33477185
  2. 重新解压到无嵌套的顶层目录:unzip p33477185_112040_Linux-x86-64.zip -d /u01/patch/33477185(确保/u01/patch/33477185/patchinfo.xml存在)
  3. 重新执行opatch apply。

4.3 现象:datapatch卡在Executing preinstall.sql无响应

原因:preinstall.sql脚本中调用的DBMS_SQLTUNE包依赖SYS用户下的SQLTUNE_PLAN_TABLE,而该表在某些自定义安装中被删除或重命名。datapatch会等待该对象存在才继续。
解决:

  1. 手动创建缺失表:
    CONNECT / AS SYSDBA CREATE TABLE sqltune_plan_table ( statement_id VARCHAR2(30), plan_id NUMBER, timestamp DATE, remarks VARCHAR2(4000), operation VARCHAR2(30), options VARCHAR2(255), object_node VARCHAR2(128), object_owner VARCHAR2(30), object_name VARCHAR2(30), object_instance NUMERIC, object_type VARCHAR2(30), optimizer VARCHAR2(255), search_columns NUMBER, id NUMBER, parent_id NUMBER, depth NUMBER, position NUMBER, cost NUMBER, cardinality NUMBER, bytes NUMBER, other_tag VARCHAR2(255), partition_start VARCHAR2(255), partition_stop VARCHAR2(255), partition_id NUMBER, other LONG, distribution VARCHAR2(30), cpu_cost NUMBER, io_cost NUMBER, temp_space NUMBER, access_predicates VARCHAR2(4000), filter_predicates VARCHAR2(4000), projection VARCHAR2(4000), time NUMBER, qblock_name VARCHAR2(30) ) TABLESPACE SYSTEM;
  2. 重新运行datapatch -verbose。

4.4 现象:RAC 环境中一个节点datapatch成功,另一个报ORA-01034: ORACLE not available

原因:datapatch在 RAC 中默认只连接本地实例。若第二个节点的监听未启动,或tnsnames.ora中LOCAL_LISTENER配置错误,datapatch无法建立连接。
解决:

  1. 在第二个节点检查监听状态:lsnrctl status,若未运行则lsnrctl start
  2. 检查LOCAL_LISTENER:
    SELECT value FROM v\$parameter WHERE name = 'local_listener'; -- 应返回类似:(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=node2-vip)(PORT=1521)))
  3. 若返回空,手动设置:ALTER SYSTEM SET LOCAL_LISTENER='(ADDRESS=(PROTOCOL=TCP)(HOST=node2-vip)(PORT=1521))' SCOPE=BOTH;
  4. 再执行datapatch。

4.5 现象:补丁安装后,expdp导出时报ORA-39126: Worker unexpected fatal error in KUPW$WORKER.PUT_DDLS

原因:该 PSU 修复了Bug 27335416(Data Pump DDL 生成逻辑缺陷),但datapatch未重编译KUPW$WORKER包体。该包在catqm.sql中定义,而datapatch有时会跳过catqm相关脚本。
解决:

  1. 手动重编译:
    CONNECT / AS SYSDBA @?/rdbms/admin/catqm.sql system temp DEFAULT @?/rdbms/admin/utlrp.sql
  2. 验证:SELECT object_name, status FROM dba_objects WHERE object_name = 'KUPW$WORKER' AND status = 'VALID';

5. 验证补丁是否真正起效:用三个真实业务场景做压力测试

装完补丁不是终点,而是验证的起点。我见过太多 DBA 在opatch lsinventory显示成功后就收工,结果两周后业务方反馈“死锁变多了”,一查发现Bug 26983812的修复根本没生效——因为datapatch被跳过了,或者v$system_fix_control中value仍为0。下面这三种验证方式,是我从某高校教务系统、某制造企业 ERP、某银行核心账务系统三个真实项目中提炼出的、能暴露“伪安装”的压力测试法。

5.1 场景一:高并发 UPDATE 主键引发的 TX 锁竞争(复现 Bug 26983812)

该 Bug 表现为:当多个会话同时UPDATE同一张表的同一行(通过主键定位)时,enq: TX - row lock contention等待时间异常增长,且v$lock中BLOCKED列持续为Y。用以下脚本模拟:

-- 创建测试表(模拟业务主表) CREATE TABLE test_tx_lock ( id NUMBER PRIMARY KEY, name VARCHAR2(100), ts DATE ); -- 插入测试数据 INSERT INTO test_tx_lock VALUES (1, 'test', SYSDATE); COMMIT; -- 开启两个 SQL*Plus 会话,分别执行: -- 会话1: UPDATE test_tx_lock SET name = 'session1' WHERE id = 1; -- 会话2(在会话1未提交时执行): UPDATE test_tx_lock SET name = 'session2' WHERE id = 1; -- 此时会话2应立即阻塞(正常行为) -- 等待 5 秒后,在会话1执行: COMMIT; -- 观察会话2的响应时间(应 ≤ 100ms)。若超过 500ms,且 `v$session_wait` 中 `event` 为 `enq: TX - row lock contention`,说明 Bug 未修复。

验证要点:在补丁安装前后,用awk '{print $1,$2}' /proc/$(pgrep -f "sqlplus.*session2")/stack抓取会话2的内核栈,修复前会看到kcbz_check_objd_typ函数深度嵌套,修复后该函数调用消失。

5.2 场景二:Data Pump 导出时的 DDL 生成崩溃(复现 Bug 27335416)

该 Bug 导致expdp在生成GRANT语句时崩溃,报ORA-39126。用最小化测试集验证:

# 创建测试用户与对象 $ sqlplus / as sysdba <<EOF CREATE USER test_dp IDENTIFIED BY test_dp; GRANT CONNECT, RESOURCE TO test_dp; CREATE TABLE test_dp.t1 (id NUMBER); INSERT INTO test_dp.t1 VALUES (1); COMMIT; EXIT; EOF # 执行导出(关键:必须指定 CONTENT=METADATA_ONLY,触发 DDL 生成) $ expdp test_dp/test_dp DIRECTORY=data_pump_dir DUMPFILE=test.dmp CONTENT=METADATA_ONLY LOGFILE=expdp.log # 检查 expdp.log: # 修复前:日志末尾出现 `ORA-39126: Worker unexpected fatal error...` # 修复后:日志末尾为 `Job "TEST_DP"."SYS_EXPORT_SCHEMA_01" successfully completed`

提示:若导出成功但日志中有ORA-39142: incompatible version,说明datapatch未更新sys.ku$_ddls视图,需手动执行@?/rdbms/admin/catqm.sql。

5.3 场景三:AWR 报告中 Top Event 的结构性变化(全局验证)

这是最可靠的“宏观验证”。该 PSU 修复了 17 个与 AWR 采集、ASH 分析相关的 Bug,包括Bug 28204707(ASH buffer 争用)。安装后,对比补丁前后的 AWR 报告:

指标补丁前(典型值)补丁后(期望值)验证方法
DB CPU在 Top 5 等待事件中占比≥ 35%≤ 15%AWR 报告 → "Top 5 Timed Events" 表
gc cr block busy平均等待时间> 10 ms< 2 msAWR 报告 → "Global Cache and Enqueue Services" 部分
SQL ordered by Elapsed Time中PL/SQL类 SQL 数量≥ 8 条≤ 2 条AWR 报告 → "SQL Statistics" → "SQL ordered by Elapsed Time"

执行命令生成对比报告:

# 补丁前快照(假设 snap_id 1000-1010) $ awrrpt.sql -s 1000 -e 1010 -dbid <dbid> -report_type html -output /tmp/awr_before.html # 补丁后快照(snap_id 1020-1030) $ awrrpt.sql -s 1020 -e 1030 -dbid <dbid> -report_type html -output /tmp/awr_after.html

重点看Top 5 Timed Events表中DB CPU行的%Total列——若从 42% 降到 11%,基本可确认Bug 26983812和Bug 28204707均已生效。

从那以后我每次给 Oracle 11.2.0.4 打 PSU,都强制走一遍这三步验证:先用v$system_fix_control确认value=1,再用datapatch -verbose日志确认catbundle.sql执行成功,最后用expdp和AWR做双盲压力测试。不是信不过 Oracle 的补丁包,而是信不过自己哪次手抖漏掉了-pdbs参数,或者哪次chown忘了加-R。希望帮到你。

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

返回列表