先查v$timezone_file.version确认当前时区版本,再查v$instance.database_status确保数据库状态为open或mounted,否则升级将失败。

确认当前时区文件版本和数据库状态
先查清楚你到底在跟哪个版本打交道,否则所有操作都是盲打。运行:SELECT VERSION FROM V$TIMEZONE_FILE; —— 注意是 V$TIMEZONE_FILE.VERSION,不是 BANNER 或 registry$database.TZ_VERSION。如果返回 14、18、26 这类小数字,基本可以断定不支持 Asia/Shanghai 这类新时区名;若已是 40+,但升级仍失败,大概率是补丁没打全或路径不对。
同时检查数据库是否处于可升级状态:SELECT DATABASE_STATUS FROM V$INSTANCE; 必须是 MOUNTED 或 OPEN(BEGIN_PREPARE 阶段要求 OPEN;BEGIN_UPGRADE 要求 STARTUP UPGRADE)。别在 RESTRICTED 模式下硬跑,会卡住或报 ORA-56920。
替换 timezlrg.dat 前必须验证 ORACLE_HOME 和 zoneinfo 路径
很多人替换完文件重启还是报 ORA-01882,根本原因是 Oracle 没读到新文件。它默认去 $ORACLE_HOME/oracore/zoneinfo/ 找 timezlrg.dat,但这个路径依赖 ORACLE_HOME 环境变量是否指向根目录(不是 bin 子目录)。Windows 下常见错误是把 ORACLE_HOME 设成 C:\oracle\product\19c\dbhome\bin,结果 Oracle 在 bin/oracore/zoneinfo/ 下扑空。
-
ORACLE_HOME必须指向 Oracle 安装根目录,例如C:\oracle\product\19c\dbhome - 确认该路径下存在
oracore\zoneinfo\timezlrg_40.dat(或对应目标版本号) - Linux 下用
ls -l $ORACLE_HOME/oracore/zoneinfo/timezlrg*.dat查实际文件;Windows 下注意大小写和扩展名是否为.dat(不是.DAT) - 如果用的是 Oracle Client(非数据库实例),同样要配对
ORACLE_HOME,否则sqlplus或 JDBC 会加载旧 client 自带的时区文件,导致ORA-01804
执行 DBMS_DST 前的强制准备动作
DBMS_DST 不是“一键升级”,它依赖数据库内部状态和会话参数。跳过这步,BEGIN_PREPARE 可能静默返回 0 行,却漏掉分区表、IOT 表或含虚拟列的表。
必须提前做:
- 清空回收站:
EXECUTE DBMS_RECYCLEBIN.PURGE('ALL');(否则某些 DDL 操作可能被阻塞) - 设置会话级隐式参数(尤其 12c+):
ALTER SESSION SET "_with_subquery" = materialize;和ALTER SESSION SET "_simple_view_merging" = TRUE; - 确认没有活跃的 DBMS_DST 操作:
SELECT * FROM DBA_DST_TAB;返回空才安全 - 手动检查关键表是否含
TIMESTAMP WITH TIME ZONE列:SELECT OWNER, TABLE_NAME, COLUMN_NAME FROM DBA_TAB_COLUMNS WHERE DATA_TYPE = 'TIMESTAMP WITH TIME ZONE';—— 如果业务表没在这列表里,DBMS_DST根本不会碰它们
补丁安装后必须重启实例并验证文件加载
下载的 timezone 补丁(如 p34698179_190000_MSWIN-x86-64)本质是更新 timezlrg.dat 和 timezone.dat。但 Oracle 不会在运行中热加载——哪怕你替换了文件,不重启,V$TIMEZONE_FILE.VERSION 仍显示旧值。
标准流程是:
- 停库:
SHUTDOWN IMMEDIATE - 替换
$ORACLE_HOME/oracore/zoneinfo/下的两个 dat 文件 - 启库:
STARTUP(不是STARTUP UPGRADE,那是 DBMS_DST 阶段用的) - 立刻查:
SELECT * FROM V$TIMEZONE_FILE;—— VERSION 必须已更新,且FILENAME显示为timezlrg_40.dat类似命名 - 如果 VERSION 没变,说明 Oracle 没加载新文件:检查文件权限(Linux)、是否被杀毒软件锁定(Windows)、
ORACLE_HOME是否被其他进程覆盖
真正容易被忽略的点是:RAC 环境下,每个节点的 $ORACLE_HOME 都得单独替换文件并重启实例,不能只动一个节点。











