Oracle 19c时区35补丁p31335037安装:OPatch成功≠完成
简介面向使用 Oracle 19c、需要把数据库时区升级至 TSTZ 35 版本的 DBA 与运维人员这份 Linux-x86-64 补丁包主要解决 ORA-39405 时区版本不一致引发的报错适用于版本升级、数据迁移或导入后出现时区差异的场景。需要留意的是补丁针对 Oracle 19.3 环境设计其他版本直接应用可能提示错误使用前应确认数据库版本与当前时区状态。压缩包共 10 个文件包含 6 个 dat 时区数据文件、2 个 xml 配置说明和 2 个 txt 文本整体约 394KB组件相对精简便于在受限环境中传输、备份与部署。已有 2570 人学习或下载说明该补丁在同类时区升级需求中具有一定参考价值。读者可获得配套的时区数据、元数据说明及安装提示文本用于核对补丁内容、验证升级结果并整理变更记录降低因时区版本不匹配造成的业务中断与排查成本。1. Oracle 19c 时区 35 补丁 p31335037opatch apply成功不等于安装完成Oracle 19c 要打时区 35 补丁p31335037Linux-x86-64 版出问题的地方几乎从来不在opatch apply那一步而在它后面。上个月给一套对账库升时区同事把 zip 解压、opatch apply、重启一气呵成opatch lspatches里也能看到 31335037结果一查v$timezone_file还是老版本——补丁只写进了 ORACLE_HOME数据库里的时区规则并未改变。等到夏令时切换那天报表里带时区的字段整体偏移一小时业务侧拿着两套对不上的流水找上门。这套流程在 19c 上太常见了一个 ORACLE_HOME、一个实例、一堆历史TIMESTAMP WITH TIME ZONE数据。二进制层和数据层是两件事装对半小时收工装漏一步就得再开一个维护窗口返工。2. 环境对齐19c 的 ORACLE_HOME、OPatch 和实例状态怎么核时区补丁最容易出的问题是“补丁打进去了但打到了另一个 ORACLE_HOME 上”。19c 的机器上很少只有一个 homeRAC 有 grid home 和 db home单机也可能因为升级、测试并存两三个 db home。动手之前先把这三样对清楚比事后查lsinventory快得多。2.1 确认当前 shell 指向哪个 ORACLE_HOME先把身份和环境变量摆明别用别人留下的会话直接开干。# 1. 当前是谁、环境变量指向哪里 id echo ORACLE_HOME$ORACLE_HOME echo ORACLE_SID$ORACLE_SID which sqlplus opatch # 2. 机器上有几个 home 在跑实例/监听 ps -ef | grep -E pmon|tnslsnr | grep -v grep # 3. 登记在册的 home 清单 cat /etc/oratab $ORACLE_HOME/OPatch/opatch lsinventory | head -20opatch lsinventory开头会打印Oracle Home的实际路径和版本号这一行必须和你想打补丁的那个 19.0.0.0.0 完全一致。which opatch也是个陷阱有些环境里/usr/local/bin/opatch是个软链指到上一个版本的 home你以为用的是自己的 OPatch其实不是。常见做法是干脆不走 PATH全程写绝对路径$ORACLE_HOME/OPatch/opatch省得怀疑人生。RAC 场景还要多确认一步补丁打在 db home 上不是 grid home。grid home 里也有oracore/zoneinfo但那套文件跟数据库时区版本没关系打错了v$timezone_file一辈子不会变。2.2 补丁包、平台和 OPatch 版本门槛p31335037 这个包拆开看就是几件事先在纸上列清楚后面执行时不容易漏。项目值怎么确认补丁号31335037文件名p31335037_190000_Linux-x86-64.zip目标版本19.0.0.0.0opatch lsinventory里的版本行平台Linux x86-64uname -m应为x86_64补丁类型Time Zone File DSTv35one-off 补丁解压后的README.txt二进制动作opatch apply需要停实例数据动作utltz_upg_check.sql/utltz_upg_apply.sql需要startup upgrade数据层可回退否升上去就降不回来OPatch 版本不够是硬门槛补丁的README.txt里会写明最低要求这版一般要 12.2.0.1.17 以上。查一下就知道够不够$ORACLE_HOME/OPatch/opatch version # 输出形如 Version: 12.2.0.1.23版本低了要换 OPatch注意是整个目录替换不是覆盖单个可执行文件把原OPatch目录改名备份新下载的 OPatch 包解压到$ORACLE_HOME下形成新的OPatch再跑一次opatch version确认。只覆盖opatch二进制、留下旧的opatch.pl和 jar 包后面prereq检查会报一堆莫名其妙的错。提示换 OPatch 之前先cp -a $ORACLE_HOME/OPatch /u01/backup/OPatch.bak出事能整目录换回来。2.3 摸底数据量和备份这一步决定窗口开多久二进制补丁十几分钟就完事真正吃时间的是第 4 章的数据升级。提前把带时区的列摸清楚能判断要不要拆窗口。-- 统计业务用户下带时区的列SYS 等系统 schema 可以排除 SELECT owner, table_name, column_name, data_type FROM dba_tab_cols WHERE data_type LIKE TIMESTAMP%WITH TIME ZONE AND owner NOT IN (SYS,SYSTEM,XDB,MDSYS,CTXSYS,ORDSYS,WMSYS,LBACSYS,DVSYS,AUDSYS) ORDER BY 1, 2;查出来的列越多、表越大utltz_upg_apply.sql跑得越久因为这一步要按新规则重算并回写这些列。经验值千万行级别的 TSTZ 数据留足两三个小时比较稳还要顺手看一眼 undo 表空间余量。备份这块别省。除了常规的 RMAN 全备我一般还会留两份“文本备份”# 记录打补丁前的补丁清单和时区版本出问题时有对照物 $ORACLE_HOME/OPatch/opatch lspatches /u01/backup/lspatches_before.txt sqlplus -S / as sysdba EOF /u01/backup/tz_before.txt SET PAGESIZE 100 SELECT version, filename FROM v$timezone_file; SELECT property_name, property_value FROM database_properties WHERE property_name LIKE DST%; EOF注意二进制补丁可以用opatch rollback -id 31335037回退但数据库的时区版本一旦升到 35 就回不去了。第 4 章那两条脚本执行之前必须有一份验证过可恢复的备份。3. 二进制落地用 OPatch 把 31335037 打进 19c 的 ORACLE_HOME这一章的动作全部在 ORACLE_HOME 层面数据库实例是停着的。流程本身不复杂烦的是那些“看起来成功、其实没生效”的中间状态。3.1 解压、看目录、读 README# 用 oracle 用户解压别用 root mkdir -p /u01/soft/patch cd /u01/soft/patch unzip -q /u01/soft/p31335037_190000_Linux-x86-64.zip # 一般会解出一个以补丁号命名的目录 ls -ld /u01/soft/patch/31335037 ls -l /u01/soft/patch/31335037典型结构里能看到etc/config/补丁元数据和 inventory 描述、files/实际要被复制到$ORACLE_HOME的文件包括oracore/zoneinfo/timezlrg_35.dat、以及README.txt。三个地方值得花五分钟看一眼sed -n 1,60p /u01/soft/patch/31335037/README.txt第一看“支持的版本和平台”确认写的是 19.0.0.0.0 和 Linux x86-64第二看“安装前置条件”通常会明确要求关闭该 home 下的所有实例和监听第三看“安装与回退命令”确认是标准opatch apply而不是需要跑什么特殊脚本。如果解压时手滑用了 root目录属主会是 root后面opatch apply复制文件阶段直接报权限错误。补救很简单chown -R oracle:oinstall /u01/soft/patch/313350373.2 两个 prereq 检查冲突和空间正式 apply 之前跑检查比打完再回退便宜太多。export ORACLE_HOME/u01/app/oracle/product/19.0.0/dbhome_1 cd /u01/soft/patch/31335037 # 检查与当前 home 已装补丁是否冲突 $ORACLE_HOME/OPatch/opatch prereq CheckConflictAgainstOHWithDetail -ph ./ # 检查 /u01 剩余空间是否够 $ORACLE_HOME/OPatch/opatch prereq CheckSystemSpace -ph ./-ph ./指的是“补丁所在目录”别写成文件的绝对路径否则会提示找不到 patch 位置。CheckConflictAgainstOHWithDetail如果报冲突先opatch lspatches看一眼是不是已经装过更高版本的时区补丁——时区补丁是有序的装过 DSTv35 之后再装 34 会直接拒绝。CheckSystemSpace一般要求几百 MB 余量空间紧张的环境经常卡在这。3.3 停实例、apply、核对 lspatches停库这一步RAC 和单机命令不同但目标一致让 ORACLE_HOME 下没有任何进程持有可执行文件。# RAC 环境 srvctl stop database -d ORCL srvctl stop listener -n $(hostname) # 单机环境 sqlplus -S / as sysdba EOF shutdown immediate; exit EOF lsnrctl stop # 最后再确认一遍这行不该有输出 ps -ef | grep -i $ORACLE_HOME | grep -v grep然后执行安装cd /u01/soft/patch/31335037 $ORACLE_HOME/OPatch/opatch apply # 脚本化场景可以用非交互 # $ORACLE_HOME/OPatch/opatch apply -silent交互模式下会列出补丁信息和目标 home要输入y确认。成功时最后一行是OPatch succeeded.日志落在$ORACLE_HOME/cfgtoollogs/opatch/下出问题第一时间去翻那里比看屏幕滚动输出靠谱。装完三件事一起核对缺一不可# 1. 补丁登记进 inventory 了 $ORACLE_HOME/OPatch/opatch lspatches | grep 31335037 # 2. 补丁详情里的描述是 Time Zone File $ORACLE_HOME/OPatch/opatch lsinventory -detail | grep -i -A3 31335037 # 3. 新的时区规则文件真的落到磁盘上了 ls -l $ORACLE_HOME/oracore/zoneinfo/ | grep -E timezlrg_35|timezone_35第 3 条最直观timezlrg_35.dat和timezone_35.dat出现在oracore/zoneinfo/下说明二进制层的时区规则文件已经就位。RAC 环境里每个节点的 db home 都要各跑一遍opatch apply只打一个节点另一个节点重启后照样读旧文件。提示此时数据库还起不来“正常营业”。二进制有了数据层的时区版本没动直接startup是可以开的但新写入的时区数据仍按旧版本规则——这就是第 1 章那个坑的成因。4. 数据层升级utltz_upg_check.sql 与 utltz_upg_apply.sql 在 19c 上的跑法二进制补丁把新规则文件放进了 home数据库里还挂着一个旧版本号。这一章要做的是把数据库的时区版本从旧值推到 35并把已有 TSTZ 数据按新规则重算一遍。两条脚本顺序不能反。4.1 为什么要startup upgrade而不是startup时区数据升级会改数据字典、会重算业务表里的 TSTZ 列整个过程不允许普通会话插进来。UPGRADE 模式正好是这个语义只允许SYSDBA连接业务账号一律连不上。export ORACLE_SIDORCL sqlplus / as sysdba SQL shutdown immediate; SQL startup upgrade;如果库本来就是 open 的必须先shutdown immediate不能从 open 直接切 UPGRADE。启动成功后可以用另一窗口验证一下“业务真的进不来”-- 在另一个 sqlplus 里用普通账号试 SELECT COUNT(*) FROM v$session WHERE con_id 0;这一步也顺便解释了为什么必须开维护窗口——它不是“慢”是“业务在这段时间里根本连不上”。4.2 跑 check 脚本把输出读明白SET SERVEROUTPUT ON SIZE UNLIMITED ?/rdbms/admin/utltz_upg_check.sql?是 SQLPlus 的内置替换变量指向当前ORACLE_HOME。如果用的不是 SQLPlus比如某些第三方客户端或者脚本里?没被展开直接写全路径$ORACLE_HOME/rdbms/admin/utltz_upg_check.sql别指望它自己认。输出里要抓四样东西当前时区版本升级前数据库认的那个版本号和你第 2 章v$timezone_file查出来的应该一致目标版本应该显示 35如果不显示说明二进制补丁没生效或者打错了 homeTSTZ 列清单脚本会列出带时区数据的表和列和你在 2.3 节自己查的结果对一下问题行如果有数据在夏令时切换瞬间落到了“不存在”或“有歧义”的时间点上这里会报出来并给出定位信息。出现第 4 类输出正确姿势是shutdown immediate后startup回正常模式把这些行的时间值改到相邻的合法时刻或者和业务确认这条数据本来就该置空再回 UPGRADE 模式重跑 check。不要抱着“先 apply 试试”的心态——apply 阶段一样会失败而且失败在中间状态收拾起来更麻烦。4.3 跑 apply 脚本、重启、重编译check 干净之后再动 apply。?/rdbms/admin/utltz_upg_apply.sql这条脚本会真正修改数据。TSTZ 数据量大的话几十分钟到几个小时都正常期间会持有表级锁、产生大量 undo 和 redo。跑的过程中盯两个视图能判断它是在干活还是卡住了-- 在另一个会话里看进度 SELECT sid, serial#, event, sql_id, seconds_in_wait FROM v$session WHERE status ACTIVE AND username SYS;跑完之后按顺序收尾SQL shutdown immediate; SQL startup; SQL ?/rdbms/admin/utlrp.sqlutlrp.sql编译失效对象时区升级会连带影响一部分依赖数据字典的存储过程、视图这一步不能省。收尾后第一件事是查版本SELECT version, filename FROM v$timezone_file; SELECT property_name, property_value FROM database_properties WHERE property_name IN (DST_PRIMARY_TT_VERSION,DST_SECONDARY_TT_VERSION);期望结果是v$timezone_file里VERSION 35DST_PRIMARY_TT_VERSION 35DST_SECONDARY_TT_VERSION 0。最后那个 0 是关键。DST_SECONDARY_TT_VERSION非 0 意味着升级处在中间状态——脚本跑到一半失败、或者被强行中断都会留下这个痕迹。这种情况下别急着回退二进制先重新跑一遍utltz_upg_check.sql看它怎么说多数时候按提示重跑 apply 就能补完实在补不完再考虑别的手段。5. 排查避坑时区补丁在 19c 上翻车的六种现场下面这几条是我和同事在 19c 打时区补丁时真踩过的。按“现象 → 原因 → 解决”记比背命令有用。5.1 OPatch 阶段的坑坑一CheckActiveFilesAndExecutables检查失败apply 直接中断现象opatch apply跑到前置检查就停提示某些文件正在被使用OPatch failed。原因ORACLE_HOME 下还有进程活着。最常见的是监听没停、某个节点实例没停干净其次是企业管控代理、备份代理挂在这个 home 下甚至是别人开着一个sqlplus会话没退。解决ps -ef | grep $ORACLE_HOME | grep -v grep把进程列出来再用fuser -v $ORACLE_HOME/bin/oracle确认谁在占用逐个清掉再 apply。停完监听记得确认lsnrctl status已经连不上。坑二apply 成功v$timezone_file还是旧版本现象opatch lspatches里明明有 31335037库也重启了查时区版本纹丝不动。原因只做了二进制层没跑第 4 章的两条脚本。这是最高频的一条也是第 1 章那个场景的成因。解决补跑utltz_upg_check.sql和utltz_upg_apply.sql。注意顺序别直接上 apply。坑三Patch is not applicable to this Oracle Home现象apply 一开始就报补丁不适用连前置检查都没过。原因三种可能——home 版本不是 19.0.0、平台不是 Linux x86-64比如下成了别的平台包、或者多 home 环境下$ORACLE_HOME指到了另一个 home。解决echo $ORACLE_HOME、uname -m、opatch lsinventory | head -20三方对齐。RAC 环境特别注意别把补丁打到 grid home 上去那里也能 apply 成功但跟数据库时区毫无关系。坑四解压目录属主不对apply 报权限错误现象apply 在复制文件阶段报Permission denied。原因图省事用 root 解压了 zip/u01/soft/patch/31335037及子目录全是 root 属主。解决chown -R oracle:oinstall /u01/soft/patch/31335037或者干脆养成习惯——所有补丁包都以 oracle 用户解压。5.2 utltz 脚本阶段的坑坑五apply 脚本报“必须在 UPGRADE 模式”现象utltz_upg_apply.sql一开始就退出提示数据库状态不对。原因startup upgrade忘了做或者中途shutdown之后顺手startup了再跑 apply 自然不认。解决shutdown immediate本文还有配套的精品资源点击获取