简介:Oracle 19c TZ41补丁包(P35099667-190000-MSWIN-x86-64.zip)面向在Windows 2008及以上环境维护Oracle 19c数据库的DBA与运维人员,用于更新时区数据库、修复与时区相关的性能与稳定性问题,保障跨时区数据处理和报表的准确性。压缩包共10个文件,以6个dat数据文件为核心,辅以2个xml配置与2个txt说明文档,整体约352KB,体积小巧但结构完整,解压后可按官方文档配合OPatch工具完成应用。已有713人学习下载,适合需要跟进官方补丁节奏、排查时区异常或准备补丁升级演练的读者参考,可据此了解补丁组成、核对先决条件并规划备份与验证流程。
1. 打补丁前先看清版本:TZ41 不是随便哪个 19c 都能上
上周帮一个朋友处理一套 Windows 上的 Oracle 19c,应用侧反馈日期计算差了整整一小时,查了半天发现是时区文件太旧,夏令时规则没跟上。这种问题不报错、不告警,只在特定日期区间算错,属于典型的玄学故障。解决办法就是打时区补丁,也就是 TZ41,对应补丁号 35099667,Windows x86-64 平台的包名是 p35099667-190000-MSWIN-x86-64.zip。这套操作在跨时区业务、账务结算、日志时间戳对齐的场景里非常常见,装不好轻则 ORA-错误连篇,重则实例起不来。下面按我实际操作的顺序,把环境、安装、配置和翻车后的救法一次讲清,适合刚接手 19c 的开发和需要复现补丁流程的运维。
2. 环境准备:19c 版本、Opatch 与目录先对齐
2.1 确认数据库版本和补丁适用性
TZ41 是时区数据升级补丁,不是任意 19c 都能直接上。动手前先把版本号、平台、已装补丁查清楚,否则 Opatch 会在冲突检查阶段直接拒绝。
# 以 oracle 用户登录后,确认数据库版本 sqlplus -v # 查看当前已安装的补丁列表 $ORACLE_HOME/OPatch/opatch lspatches # 查看 Opatch 自身版本,19c 一般要求 12.2.0.1.17 以上 $ORACLE_HOME/OPatch/opatch versionsqlplus -v输出里要能看到 19.0.0.0.0 这类版本串,确认是 19c 而不是 12c 或 21c。opatch lspatches用来核对是否已经打过更高版本的时区补丁,如果列表里已有 TZ41 或更新的时区补丁,就不用重复打。opatch version低于 12.2.0.1.17 时,常见做法是先把 Opatch 升到对应版本,否则解压后的补丁目录可能识别不了。我一般会把这几个输出贴到变更单里,后面出问题好回溯。
2.2 Windows 平台的前置检查
Windows 上跑 19c,补丁安装对权限和路径比较敏感。解压目录不要放在带空格或中文的路径下,我习惯放在D:\patch\35099667这种纯英文短路径。另外确认 Oracle 服务是以哪个账户启动的,补丁过程需要能停库、改文件,权限不够会在应用阶段报拒绝访问。
# 检查 ORACLE_HOME 环境变量是否指向正确的 19c 安装目录 echo %ORACLE_HOME% # 确认监听和实例当前状态,打补丁前应处于关闭状态 lsnrctl status sqlplus / as sysdba SQL> select status from v$instance;echo %ORACLE_HOME%在 cmd 下执行,输出应类似D:\app\oracle\product\19.0.0\dbhome_1。如果变量为空,说明当前会话没继承系统变量,需要手动 set 或改用完整路径调用 Opatch。v$instance的 status 必须是 OPEN 之外的状态才能继续,正常流程是先shutdown immediate再打补丁。监听可以先停,避免补丁期间有连接进来干扰。
2.3 备份:这一步不能省
时区补丁会改动$ORACLE_HOME/oracore/zoneinfo下的时区文件和部分二进制,回滚虽然 Opatch 支持,但前提是补丁前有完整备份。我一般做两件事:一是用 RMAN 做一次全备或至少备份 system 表空间,二是把ORACLE_HOME下的OPatch目录和oracore目录整体复制一份到别的盘。
# 备份 oracore 目录,Windows 下用 robocopy 更稳 robocopy D:\app\oracle\product\19.0.0\dbhome_1\oracore D:\backup\oracore_before_tz41 /E # 备份 Opatch 的补丁清单 copy D:\app\oracle\product\19.0.0\dbhome_1\OPatch\oraInst.loc D:\backup\robocopy /E会连空目录一起复制,保证结构完整。oraInst.loc记录了 inventory 位置,回滚时如果 inventory 出问题,这个文件能救命。备份完别急着删,等补丁验证通过、业务跑过一轮再清理。
3. 安装 TZ41:解压、冲突检查与 apply
3.1 解压补丁包并核对目录结构
把p35099667-190000-MSWIN-x86-64.zip解压到D:\patch\35099667,解压后应该能看到一个以补丁号命名的子目录,里面包含etc、files和README.txt。目录层级不对是 Opatch 报错的高频原因,很多人多套了一层文件夹,导致opatch apply找不到etc/config。
# 解压后进入补丁目录,确认关键文件存在 cd D:\patch\35099667\35099667 dir # 应能看到 README.txt、etc、files 等如果dir里只有一层35099667文件夹而没有etc,说明解压多了一层,需要再进一级。README.txt里会写明适用的版本范围和前置补丁,花两分钟扫一眼能省掉后面半小时的排查。
3.2 用 Opatch 做冲突检查
正式 apply 之前先跑一遍冲突检查,这一步能提前暴露补丁冲突、inventory 不一致等问题,比直接 apply 失败后再回滚省事得多。
# 进入补丁目录执行冲突检查 cd D:\patch\35099667\35099667 %ORACLE_HOME%\OPatch\opatch prereq CheckConflictAgainstOHWithDetail -ph ./-ph ./表示以当前目录作为补丁目录。输出里如果出现Conflicts字样,要看清是哪个补丁冲突,常见情况是已经装过更高版本的时区补丁,或者某个 one-off 补丁覆盖了相同文件。冲突不解决不要强行 apply,Opatch 虽然支持-force,但强推之后实例起不来的案例不少。
3.3 执行 apply 并观察输出
确认无冲突后,关闭实例和监听,执行 apply。Windows 下建议用管理员身份的 cmd,避免文件写入权限问题。
# 关闭实例和监听 sqlplus / as sysdba SQL> shutdown immediate; SQL> exit lsnrctl stop # 执行补丁安装 cd D:\patch\35099667\35099667 %ORACLE_HOME%\OPatch\opatch applyapply 过程中会提示是否继续,输入y确认。输出末尾出现OPatch succeeded才算成功。如果中途报Prerequisite check "CheckActiveFilesAndExecutables" failed,说明还有 Oracle 进程占用文件,需要确认所有服务已停,必要时在服务管理器里把 Oracle 相关服务也停掉。apply 完成后不要立刻启动数据库,先做下面的配置和验证。
4. 配置与生效:时区版本、数据库重启与参数确认
4.1 确认时区文件版本已更新
补丁 apply 成功后,oracore/zoneinfo下的时区文件会被替换。可以先从文件层面确认版本号,再进数据库查。
# 查看时区文件版本 %ORACLE_HOME%\bin\oracle -? # 更直接的方式是查数据库 sqlplus / as sysdba SQL> SELECT version FROM v$timezone_file;v$timezone_file返回的 version 应该对应 TZ41 的版本号(19c 下通常是 41)。如果还是旧值,说明补丁没真正生效,需要回看 apply 日志。这个查询在数据库启动后执行,所以顺序是先启库再查。
4.2 启动实例并检查时区相关参数
启动实例后,除了v$timezone_file,还要确认数据库的时区设置和业务依赖的列没有异常。时区补丁改的是规则数据,不改数据库时区本身,但依赖TIMESTAMP WITH TIME ZONE的表在跨规则边界时行为会变。
# 启动监听和实例 lsnrctl start sqlplus / as sysdba SQL> startup; # 查看数据库时区和时区文件版本 SQL> SELECT dbtimezone FROM dual; SQL> SELECT version FROM v$timezone_file; # 检查是否有失效对象 SQL> SELECT COUNT(*) FROM dba_objects WHERE status = 'INVALID';dbtimezone一般保持原值不动,补丁不要求改它。dba_objects里 invalid 数量如果比补丁前明显增多,常见做法是跑一遍utlrp.sql重新编译。时区补丁本身不涉及大量 PL/SQL 对象,invalid 增多通常说明补丁过程中有对象被锁或编译中断,需要单独处理。
4.3 应用侧需要配合的检查
数据库侧生效不代表业务侧就对了。应用如果缓存了时区规则,或者连接池里持有旧会话,需要重启应用或刷新连接池。我一般会挑一个跨夏令时切换的时间点做回归,比如用FROM_TZ和AT TIME ZONE构造几个边界时间做对比。
-- 构造夏令时边界时间,验证转换结果 SELECT FROM_TZ(TIMESTAMP '2024-03-10 02:30:00', 'America/New_York') AT TIME ZONE 'UTC' AS utc_time FROM dual;这条语句在旧时区文件下可能返回与预期差一小时的结果,打完 TZ41 后应与官方时区规则一致。业务侧如果有账务日切、定时任务依赖本地时间,建议在低峰期做一次实际跑批验证,别只看 SQL 结果。
5. 避坑与排查:TZ41 安装中最容易翻车的几件事
5.1 现象:opatch apply 报 “No patch found”
原因通常是解压层级多了一层,或者-ph指向的目录里没有etc/config。解决方法是进到真正包含etc的那一级再执行,或者用-ph指定完整路径。我见过有人把 zip 直接解压到桌面再拷进服务器,路径里带中文,Opatch 直接读不了,换成纯英文短路径就好了。
5.2 现象:补丁装完实例起不来,报 ORA-00406
原因是补丁文件与当前ORACLE_HOME的二进制不匹配,常见于混用了不同补丁集的 Opatch 或者之前强推过冲突补丁。解决方法是先用opatch rollback -id 35099667回滚,回滚前确认备份可用,回滚后检查opatch lspatches是否恢复到补丁前状态,再重新核对版本和冲突。
5.3 现象:v$timezone_file 版本没变
原因是补丁 apply 成功但数据库没重启,或者查的是另一个实例。解决方法是确认当前连接的实例和ORACLE_HOME一致,执行shutdown immediate后重新startup,再查一次。如果还是旧值,去看$ORACLE_HOME/OPatch/下的 apply 日志,确认文件是否真的被替换。
5.4 现象:应用时间仍然差一小时
原因是应用侧缓存或连接池未刷新,也可能是应用自己维护了一份时区表。解决方法是重启应用、清连接池,并检查应用配置里是否有独立的时区数据文件。数据库补丁只管数据库侧,应用侧的时区库需要单独更新,这一点在跨系统对接时特别容易漏。
5.5 现象:回滚后 inventory 报错
原因是补丁过程中 inventory 被写坏,或者oraInst.loc指向的路径不可写。解决方法是先用备份的oraInst.loc覆盖回去,确认 inventory 目录权限,再执行回滚。回滚前一定确认opatch lspatches里能看到 35099667,看不到就没法按补丁号回滚,只能走文件级恢复。
6. 装完怎么验证:三条查询加一次边界回归
补丁装完不等于跑通,我习惯用三条查询加一次边界回归来收尾。第一条查v$timezone_file的 version,确认是 41;第二条查dba_registry里组件状态,确认没有因为补丁变成 INVALID;第三条查dba_objects的 invalid 数量,和补丁前做对比。
-- 时区文件版本 SELECT version FROM v$timezone_file; -- 组件状态 SELECT comp_name, status FROM dba_registry ORDER BY comp_name; -- 失效对象数量 SELECT COUNT(*) FROM dba_objects WHERE status = 'INVALID';v$timezone_file返回 41 是硬指标。dba_registry里各组件应为 VALID,如果有 INVALID,先跑utlrp.sql再复查。invalid 对象数量和补丁前差异不大才算正常,明显增多要查是哪个 schema 下的对象。
边界回归我一般用两条 SQL 对比:一条构造夏令时开始前的时间,一条构造结束后时间,分别转 UTC 看结果是否符合预期。再挑一个业务实际用到的定时任务,在测试环境跑一轮,确认日切时间没偏移。做完这些,把opatch lspatches的输出、三条查询结果和回归截图一起归档,下次再打时区补丁直接对照。
血泪经验是:时区补丁的坑大多不在 apply 本身,而在“以为装完了”之后的验证缺失。从那以后我每次打 TZ41 都强制走一遍版本查询、组件状态和边界回归,哪怕变更窗口再紧也不跳过。希望帮到你。
本文还有配套的精品资源,点击获取