简介Oracle 19c TZ41 补丁P35099667-190000-MSWIN-x86-64面向 Windows 2008 及以上环境下维护 Oracle 19c 的数据库管理员与运维人员主要用于更新时区数据并规避与时间区域相关的性能、安全和稳定性问题适合跨时区业务、补丁核对及日常巡检场景。压缩包共 10 个文件大小约 352KB以 6 个 dat 数据文件为主辅以 2 个 xml 配置文件和 2 个 txt 说明文档便于识别补丁内容、阅读说明并核对配置项。已有 712 人学习说明该补丁在 Windows 平台 Oracle 维护中具有实际参考需求。读者可获得 TZ41 时区更新所需的文件集合、说明材料与配置依据用于应用前的内容确认、版本比对和问题排查降低因时区规则不一致造成的报表偏差与运行风险。1. Oracle 19c TZ41 补丁 p35099667 在 Windows 上安装别被 zip 后缀骗了Oracle 19c TZ41 补丁 p35099667-190000-MSWIN-x86-64.zip 拿到手时很多人第一反应是双击解压、找 setup结果发现里面没有安装程序。这不是普通的 Windows 安装包而是给 Oracle 19c Windows x86-64 用的时区补丁ORACLETZ41 对应的就是这一类时区文件更新。装不好不会立刻报错可能会在跨时区业务、日期计算、数据泵导入时突然翻车。下面按我实际装库的顺序从版本核对、OPatch 预检、apply、datapatch 到验证一步步走。2. 装前核对Oracle 19c Windows x86-64 的版本、OPatch 和 p35099667 补丁边界2.1 先确认实例版本与时区文件TZ41 不是随便哪个 19c 都能套补丁文件名里的190000和MSWIN-x86-64不是装饰。前者对应 19c 基线后者说明这是 Windows 64 位平台补丁拿到 Linux 的 Oracle Home 里执行opatch apply只会得到一句不适用。TZ41 也不是“装完就多一个功能”的普通补丁它更新的是数据库时区文件影响TIMESTAMP WITH TIME ZONE、跨时区转换、数据泵和部分日期函数的结果。我一般在装之前先连进实例把版本、时区文件和已经打过的 SQL 补丁查一遍。不要只看sqlplus -v那只说明客户端版本要进库查v$instance和v$timezone_file。如果时区文件已经是 41先确认是不是同一补丁已经装过不要重复执行。查询命令如下-- 以 sysdba 身份登录后执行先确认实例版本和时区文件版本 set pagesize 200 linesize 200 select banner_full from v$version; select version_full from v$instance; select * from v$timezone_file; -- 查最近打过的 SQL 补丁确认 35099667 是否已经注册 select patch_id, patch_type, action, status, description, action_time from dba_registry_sqlpatch order by action_time desc;banner_full能看到 19c 的具体版本version_full用来确认当前实例和 ORACLE_HOME 对得上。v$timezone_file里重点看VERSIONTZ41 装完后这里应该落到 41如果还是旧值说明补丁文件进了 Oracle Home但数据库时区数据没有完成升级。dba_registry_sqlpatch用来判断这个补丁是否已经注册过避免在同一个库上重复跑datapatch。这里有一个容易忽略的边界单实例和 CDB/PDB 的检查方式不完全一样。CDB 里要在根容器确认 SQL 补丁注册情况PDB 要确认是否处于 READ WRITE 且已经打开。如果 PDB 没开datapatch可能只处理了部分容器后面查dba_registry_sqlpatch就会看到记录不完整。常见做法是先show pdbs把需要处理的 PDB 全部打开再执行补丁后的 SQL 注册。注意如果v$timezone_file已经是 41而dba_registry_sqlpatch里没有 35099667不要急着判断“补丁不用装”。先看是不是之前用别的补丁号更新过时区文件再对照补丁 README 的冲突说明处理。2.2 OPatch 检查Windows 下 opatch.bat 的路径和 JavaWindows 上装 Oracle 补丁真正干活的不是安装向导而是%ORACLE_HOME%\OPatch\opatch.bat。很多人卡在第一步在普通 cmd 里直接敲opatch系统提示找不到命令。原因不是 OPatch 没装而是 PATH 里没有%ORACLE_HOME%\OPatch或者当前窗口没有设置ORACLE_HOME。我习惯先开一个管理员 cmd把环境变量固定下来再执行版本检查和 inventory 备份。-- 以管理员身份打开 cmd先固定 ORACLE_HOME 和 ORACLE_SID set ORACLE_HOMED:\app\oracle\product\19.0.0\dbhome_1 set ORACLE_SIDORCL set PATH%ORACLE_HOME%\bin;%ORACLE_HOME%\OPatch;%PATH% -- 确认 OPatch 能启动并记录当前补丁清单 cd /d %ORACLE_HOME%\OPatch opatch.bat version opatch.bat lsinventory -detail C:\patch_tmp\before_lsinventory.txtORACLE_HOME必须指向当前实例实际使用的 Oracle Home不是客户端目录。ORACLE_SID要和OracleServiceORCL里的实例名一致否则后面datapatch可能连到另一个库。opatch.bat version能正常输出说明 OPatch 自身和 Java 环境基本可用lsinventory -detail输出到文件是为了出问题时能对比安装前后差异也是回滚时的后悔药。Windows 上还有一个坑不要随手把系统JAVA_HOME指到某个新版本 JDK然后指望 OPatch 跟着用。Oracle 的 OPatch 通常认自己目录下的运行时或者认 Oracle Home 里的 Java 环境。系统 Java 改乱了opatch.bat可能一启动就报找不到类。我的做法是只检查 OPatch 能不能跑不改全局 Java 变量如果确实报 Java 相关错误先看%ORACLE_HOME%\OPatch下的日志和 README 要求再决定是否按补丁说明更新 OPatch。如果opatch.bat version输出了版本但补丁 README 里写的最低 OPatch 版本更高不要硬装。先按补丁包自带的说明升级 OPatch再回到prereq检查。OPatch 版本不够时apply有时不会在第一步报错而是走到一半提示补丁不适用那个时候 Oracle Home 里可能已经写入了部分文件处理起来更麻烦。2.3 停库与备份先停监听还是先停实例补丁安装期间最怕文件被占用。Windows 上 Oracle 的进程不像 Linux 那样容易看出来服务没停净opatch apply可能在中途报文件无法替换。我的顺序是先通知应用断连接停 EM 或 dbconsole如果开了停监听再关实例不要直接去任务管理器结束oracle.exe。结束进程看似快后面起库时可能留下需要恢复的实例。-- 先停监听减少新连接进入 lsnrctl stop -- 再关实例确保数据文件和控制文件正常关闭 sqlplus / as sysdba SQL shutdown immediate SQL exit -- 如果实例以 Windows 服务方式运行确认服务状态 sc query OracleServiceORCL sc query OracleTNSListenerlsnrctl stop只停监听不会关实例shutdown immediate会回滚未提交事务并正常关闭实例。服务名在不同环境里可能是OracleServiceORCL、OracleTNSListener也可能带 Oracle Home 前缀先用sc query state all | findstr /i OracleService OracleTNSListener查清楚再停。补丁安装前至少做两件事数据库有可用备份lsinventory有安装前快照。生产库不要省这一步时区补丁回退比普通补丁更绕。-- 安装前把 OPatch 清单和关键目录信息留档 mkdir C:\backup\before_tz41 opatch.bat lsinventory -detail C:\backup\before_tz41\lsinventory_before.txt dir /s %ORACLE_HOME%\OPatch C:\backup\before_tz41\opatch_dir.txtlsinventory_before.txt用来对比补丁安装前后多了哪些 patchopatch_dir.txt在 OPatch 自身出问题时能快速看目录结构。数据库备份按现有策略走RMAN 也好存储快照也好关键是确认可恢复。补丁装坏了还有机会退时区数据改错了再想回退成本会高很多。3. 解压与预检p35099667 补丁目录、README 和 opatch prereq 怎么跑3.1 解压到短路径给 OPatch 一个不带空格和中文的目录补丁 zip 不要放在桌面也不要解压到带中文、带空格的路径。OPatch 对路径的处理没有想象中宽容路径里空格多了某些参数会被截断最后报“补丁位置无效”。我一般固定用C:\patch_tmp这种短路径先建目录再用 PowerShell 解压。解压后要确认目录层级真正给opatch apply用的目录里应该能看到etc、files这类子目录而不是只有一层 zip 文件名。# 以管理员身份打开 PowerShell建立短路径并解压补丁 New-Item -ItemType Directory -Force -Path C:\patch_tmp\35099667 | Out-Null Expand-Archive -Path C:\patch_tmp\p35099667-190000-MSWIN-x86-64.zip -DestinationPath C:\patch_tmp\35099667 -Force # 查看解压后的目录层级确认补丁根目录 Get-ChildItem C:\patch_tmp\35099667Expand-Archive的-DestinationPath指向临时目录-Force用于覆盖旧解压结果。解压完不要急着opatch apply先用Get-ChildItem或dir看目录。如果看到的是C:\patch_tmp\35099667\35099667\etc说明补丁根目录多了一层后面-phBaseDir和apply都要指到里层如果直接看到etc就指外层。这个层级判断错是后面“不是有效补丁位置”的常见来源。解压后的目录权限也要看一下。如果当前用户对C:\patch_tmp没有写权限OPatch 在解压日志或临时文件时可能失败。把补丁目录放在系统盘根目录下通常没问题但不要放在只读共享盘或同步盘里。同步盘在补丁安装期间可能锁定文件导致 OPatch 读写 inventory 时出现异常。3.2 读 README 的三处OPatch 版本、冲突补丁、时区升级补丁目录里的 README 不是摆设。TZ41 这种时区补丁README 里至少有三处要确认OPatch 最低版本、冲突补丁列表、安装后是否必须执行时区升级脚本。不同补丁包的 README 格式不完全一样有的叫README.html有的还有README.txt。先看文件列表再打开对应文件不要凭经验跳过。-- 查看补丁目录里的说明文件和关键子目录 dir /b C:\patch_tmp\35099667\35099667 dir /b C:\patch_tmp\35099667\35099667\etcdir /b只列文件名方便确认 README 和etc是否存在。etc目录里通常放补丁元数据files目录里是要替换或新增的文件。README 里的 OPatch 版本要求要和opatch.bat version的输出对比冲突补丁要拿lsinventory里的 patch 列表对照时区升级部分要确认是datapatch自动处理还是需要单独跑utltz_upg_check.sql和utltz_upg_apply.sql。我一般把 README 里的关键信息抄到安装记录里至少留四项补丁号、适用平台、OPatch 要求、安装后动作。这样后面datapatch报错时能快速判断是补丁本身的问题还是漏了某个后置步骤。补丁包里的说明和当前库的实际情况冲突时以补丁 README 和当前 Oracle Home 的lsinventory为准不要拿别的库的经验硬套。注意README 里的“Post-installation”部分要逐条看。时区补丁经常要求数据库重启甚至要求先进入升级模式执行脚本漏掉这一步opatch lspatches能看到补丁号但v$timezone_file仍然是旧版本。3.3 opatch prereq 与报告模式先把“能不能装”验证掉正式apply之前先跑prereq CheckApplicable和apply -report。前者检查补丁是否适用于当前 Oracle Home后者模拟应用过程但不真正改文件。很多人省掉预检直接apply结果在交互提示里看到一堆冲突才回头查时间成本更高。预检命令要在%ORACLE_HOME%\OPatch目录下执行补丁路径指向含etc的那一层。cd /d %ORACLE_HOME%\OPatch -- 检查补丁是否适用于当前 Oracle Home opatch.bat prereq CheckApplicable -phBaseDir C:\patch_tmp\35099667\35099667 -- 检查补丁与当前 Oracle Home 的冲突详情 opatch.bat prereq CheckConflictAgainstOHWithDetail -phBaseDir C:\patch_tmp\35099667\35099667 -- 报告模式跑一遍不改文件只看过程 opatch.bat apply C:\patch_tmp\35099667\35099667 -reportCheckApplicable通过说明补丁平台和 Oracle Home 基本匹配CheckConflictAgainstOHWithDetail用来发现已安装补丁冲突apply -report会走一遍应用流程输出将要执行的动作但不会真正写入。预检报错时不要硬上先把错误日志里的补丁号和路径抄出来对照 README 和lsinventory查。预检通过后再做正式安装心里会踏实很多。如果-report阶段提示某些文件将被覆盖先确认这些文件是否被其他补丁改过。Windows 上 Oracle Home 里有些文件会被多个补丁共享冲突不一定代表不能装但需要按 README 的冲突处理顺序来。我的习惯是预检输出全部留档正式 apply 的输出也重定向到文件后面出问题能对比两次输出差异。4. 正式安装opatch apply、datapatch 和时区脚本的执行顺序4.1 管理员 cmd 执行 opatch apply别在资源管理器里双击正式安装必须用管理员 cmd不要双击opatch.bat。双击运行时工作目录和权限都不对OPatch 可能找不到ORACLE_HOME也可能没有权限写 inventory。执行前确认实例已经关闭、监听已经停止、补丁目录层级正确然后进入 OPatch 目录执行apply。过程中会提示是否继续确认补丁号和 Oracle Home 无误后再输入y。-- 管理员 cmd 中执行先确认环境变量 echo %ORACLE_HOME% echo %ORACLE_SID% cd /d %ORACLE_HOME%\OPatch opatch.bat apply C:\patch_tmp\35099667\35099667echo %ORACLE_HOME%和echo %ORACLE_SID%是安装前最后一道确认。apply的补丁路径要指到含etc的目录。执行过程中 OPatch 会检查 inventory、备份部分文件、应用补丁并更新清单。看到OPatch succeeded才算文件层面完成但这不代表数据库时区数据已经升级后面还有datapatch和时区脚本。如果apply中断不要直接重跑。先看%ORACLE_HOME%\cfgtoollogs\opatch下的日志确认是文件占用、权限问题还是补丁冲突。中断后 Oracle Home 可能处于部分应用状态盲目重跑可能让 inventory 和实际文件不一致。必要时按日志提示回滚或恢复备份再重新预检。-- 安装后先确认补丁出现在清单里 cd /d %ORACLE_HOME%\OPatch opatch.bat lspatches opatch.bat lsinventory -detail C:\backup\after_tz41_lsinventory.txtlspatches输出当前 Oracle Home 已应用的补丁列表lsinventory -detail留档用于对比。此时补丁文件已经进了 Oracle Home但数据库还没有注册 SQL 变更。不要在这个阶段启动业务连接先把datapatch和时区升级处理完。4.2 datapatch -verbose数据库要 OPENPDB 要 READ WRITEdatapatch负责把补丁里的 SQL 变更注册到数据库包括时区相关的数据字典变更。执行前数据库要处于 OPEN 状态CDB 里的 PDB 要打开到 READ WRITE。如果 PDB 没开datapatch可能跳过对应容器后面查dba_registry_sqlpatch就会看到补丁记录不完整。先起库、开 PDB再进 OPatch 目录执行。-- 启动实例到 OPEN并把 PDB 打开到 READ WRITE startup show pdbs alter pluggable database all open;-- 在 OPatch 目录执行 datapatch输出详细过程 cd /d %ORACLE_HOME%\OPatch datapatch -verbosestartup把实例带到 OPENshow pdbs看容器状态alter pluggable database all open把 PDB 打开。datapatch -verbose会逐个容器注册 SQL 补丁输出里能看到补丁号和执行状态。Windows 上有的环境对应datapatch.bat如果直接敲datapatch不识别就在 OPatch 目录下看实际文件名再执行。执行完再查dba_registry_sqlpatch确认 35099667 的记录是 SUCCESS。-- 检查 SQL 补丁注册结果 select patch_id, action, status, description from dba_registry_sqlpatch where patch_id 35099667;action一般是APPLYstatus应该是SUCCESS。如果查不到记录先确认是不是在正确的容器里查再确认datapatch输出里有没有跳过该容器。如果状态是FAILED不要继续跑时区脚本先看datapatch日志定位失败语句。SQL 补丁失败和文件补丁失败处理方式不同前者往往需要回退 SQL 变更或恢复数据库。4.3 时区升级脚本check 先行apply 后重启TZ41 补丁的文件应用和 SQL 注册完成后还要确认数据库时区文件是否真正升级。常见做法是先跑utltz_upg_check.sql检查再按 README 跑utltz_upg_apply.sql。不要一上来就执行 apply先看检查输出提示是否需要升级、是否有不兼容数据。时区升级涉及数据字典和已有时间戳数据生产库必须提前备份。-- 先关闭实例进入升级模式执行检查脚本 shutdown immediate startup upgrade ?/rdbms/admin/utltz_upg_check.sqlshutdown immediate正常关库startup upgrade进入升级模式?是 SQL*Plus 里指向 Oracle Home 的写法。检查脚本会输出当前时区版本、目标版本和需要关注的对象。如果输出提示可以继续再执行 apply 脚本如果提示有异常数据或需要先处理的对象先停下来按提示处理不要强行往下走。-- 检查通过后执行时区升级然后正常重启 ?/rdbms/admin/utltz_upg_apply.sql shutdown immediate startuputltz_upg_apply.sql执行完后再正常启动实例。不同补丁包的 README 可能要求先执行datapatch再跑时区脚本也可能要求顺序相反以补丁目录里的说明为准。Windows 下如果?不识别换成完整路径D:\app\oracle\product\19.0.0\dbhome_1\rdbms\admin\utltz_upg_check.sql。脚本执行期间不要开业务连接避免时区数据升级过程中有并发写入。4.4 启库、启监听、检查服务与告警日志时区升级完成后启动监听和服务检查告警日志里有没有 ORA- 错误。Windows 服务启动顺序一般是先起实例服务再起监听如果实例以服务方式管理可以用net start也可以让服务自动启动。启动后连进去查时区文件版本和补丁注册状态再让应用逐步恢复连接。-- 启动监听和服务检查服务状态 lsnrctl start net start OracleServiceORCL net start OracleTNSListener sc query OracleServiceORCL sc query OracleTNSListenerlsnrctl start启动监听net start启动 Windows 服务。服务名按实际环境替换不要照抄。sc query看服务是否处于 RUNNING。启动后马上去看告警日志路径通常在%ORACLE_BASE%\diag\rdbms\%ORACLE_SID%\%ORACLE_SID%\trace\alert_%ORACLE_SID%.log。重点看启动过程中有没有时区相关错误、数据字典错误或补丁注册失败。-- 启动后做一次快速确认 select * from v$timezone_file; select patch_id, action, status from dba_registry_sqlpatch where patch_id 35099667; select instance_name, status from v$instance;v$timezone_file看时区版本是否到 41dba_registry_sqlpatch看 SQL 补丁状态v$instance确认实例正常打开。三项都正常再放应用连接。如果时区版本还是旧值回到 README 确认时区脚本是否执行、数据库是否重启过、PDB 是否都处理到。5. 避坑与排查TZ41 补丁在 Windows 上最容易翻车的 5 个点5.1 补丁目录层级错apply 报不是有效补丁位置现象执行opatch apply后提示补丁位置无效或者prereq找不到etc目录。原因通常不是补丁坏了而是解压后多了一层目录命令指向了外层文件夹。比如补丁实际在C:\patch_tmp\35099667\35099667命令却写成了C:\patch_tmp\35099667。OPatch 找不到补丁元数据就会拒绝继续。解决先用dir /b看目录里有没有etc和files。有etc的那一层才是补丁根目录。prereq和apply都指向这一层不要指到 zip 文件也不要指到上一级。路径里不要带空格和中文长度尽量短。预检通过后再执行正式 apply避免在正式安装阶段才发现路径问题。5.2 OPatch 版本不够或 Java 路径乱预检失败现象opatch.bat version能跑但prereq CheckApplicable报 OPatch 版本不满足要求或者opatch.bat一启动就报 Java 类找不到。原因可能是补丁 README 要求更高版本的 OPatch也可能是系统JAVA_HOME被改过OPatch 没有用自己目录下的运行时。Windows 上多个 Oracle 产品共存时PATH 里很容易混进别的 Java。解决先看补丁 README 的 OPatch 要求再对比opatch.bat version输出。版本不够就按补丁说明升级 OPatch不要直接改系统 Java。Java 报错时检查%ORACLE_HOME%\OPatch下的日志确认 OPatch 使用的是哪套运行时。临时把 PATH 里其他 Java 路径挪到后面再开一个新的管理员 cmd 重试。改完环境变量要重新开窗口旧窗口不会自动生效。5.3 服务未停净文件占用导致 apply 中断现象opatch apply执行到一半报文件无法替换、无法写入或 inventory 更新失败。原因通常是实例、监听、dbconsole 或某个客户端进程还占着 Oracle Home 里的文件。Windows 上服务停了后台进程不一定马上退出有时应用连接没断干净实例也关不彻底。解决先lsnrctl stop再shutdown immediate然后sc query确认服务状态。用tasklist | findstr /i oracle看还有没有残留进程。不要直接结束oracle.exe除非确认实例已经正常关闭。补丁中断后不要立刻重跑先看cfgtoollogs\opatch日志确认是文件占用还是权限问题。必要时回滚或恢复 Oracle Home 备份再重新预检。5.4 datapatch 没跑或 PDB 未开SQL 补丁未注册现象opatch lspatches能看到 35099667但dba_registry_sqlpatch查不到记录或者只有部分容器有记录。原因可能是apply后直接起业务漏了datapatch也可能是 CDB 里 PDB 没有打开到 READ WRITEdatapatch跳过了对应容器。解决先show pdbs确认所有需要处理的 PDB 都是 READ WRITE再在 OPatch 目录执行datapatch -verbose。执行完分别到根容器和 PDB 里查dba_registry_sqlpatch。如果状态是 FAILED看datapatch日志里的失败语句不要继续跑时区脚本。SQL 补丁失败要先处理失败原因必要时回退 SQL 变更再重新注册。5.5 时区文件没升级跨时区查询仍异常现象补丁清单里有 35099667dba_registry_sqlpatch也是 SUCCESS但v$timezone_file还是旧版本跨时区查询结果和预期不一致。原因通常是只做了文件 apply 和datapatch漏了utltz_upg_check.sql/utltz_upg_apply.sql或者执行了脚本但没有正常重启实例。解决回到补丁 README 的 Post-installation 部分按顺序执行检查脚本和升级脚本。执行前做数据库备份执行时避免业务连接。升级完成后shutdown immediate再startup不要用startup force代替正常关闭。启动后再查v$timezone_file确认版本到 41。如果脚本报错先处理报错对象不要反复重跑 apply 脚本。6. 装完怎么验证跑通用 V$TIMEZONE_FILE 和 lspatches 做双重确认补丁装完不要只看一句OPatch succeeded。我一般做三层确认文件层看opatch lspatches数据库层看dba_registry_sqlpatch时区层看v$timezone_file。三层都对上才让应用恢复连接。下面这组查询可以直接抄改一下 SID 和补丁号就行。-- 数据库层和时区层一起查 select patch_id, action, status, description from dba_registry_sqlpatch where patch_id 35099667; select * from v$timezone_file; select instance_name, status from v$instance;-- 文件层确认补丁在 Oracle Home 清单里 cd /d %ORACLE_HOME%\OPatch opatch.bat lspatches | findstr 35099667dba_registry_sqlpatch里status要是SUCCESSv$timezone_file的版本要是 41v$instance要是 OPEN。opatch lspatches能过滤到 35099667说明文件层已经写入。三项里任何一项对不上都不要把问题留给业务去发现。最后再看一眼告警日志确认启动过程中没有时区相关错误或数据字典错误。验证项命令或视图合格标准补丁文件opatch lspatches能看到 35099667SQL 注册dba_registry_sqlpatch35099667 状态为 SUCCESS时区文件v$timezone_fileVERSION 为 41实例状态v$instanceSTATUS 为 OPEN告警日志alert_SID.log无时区升级相关 ORA- 错误这份 p35099667-190000-MSWIN-x86-64.zip 解决的是 Oracle 19c 在 Windows x86-64 上的 TZ41 时区文件更新装完后的验证比安装本身更值得花时间。从那以后我每次打时区补丁都强制走一遍“lspatches dba_registry_sqlpatch v$timezone_file”三重确认不靠记忆判断。希望帮到你。本文还有配套的精品资源点击获取