oracle升级后dbms_dst报ora-30088或ora-56920,根本原因是时区文件版本(v$timezone_file.version)与数据库不匹配;需下载对应timezlrg.dat替换$oracle_home/oracore/zoneinfo/下文件并重启实例,再执行dbms_dst操作。
oracle 升级后 dbms_dst 包报错 ora-30088 或 ora-56920 怎么办
升级 oracle(尤其是跨大版本,如 12.1 → 19c)后,dbms_dst 包常因时区文件(timezone file)不匹配直接失效——不是权限问题,也不是没执行,而是底层 timezlrg.dat 和数据库已加载的时区版本对不上。
典型现象:调用 DBMS_DST.BEGIN_PREPARE 报 ORA-30088: datetime/interval precision is out of range,或 DBMS_DST.FIND_CONFLICTS 报 ORA-56920: a running DST patch operation is not allowed,其实根本没在运行任何操作。
- 先确认当前时区文件版本:
SELECT * FROM v$timezone_file;—— 注意VERSION字段,不是BANNER - 查 Oracle 官方文档对应版本的「Timezone File Version」,比如 19c 默认用 v42,但升级前可能是 v32;版本不一致就必然触发上述错误
- 别急着跑
DBMS_DST的 prepare 步骤,先同步时区文件:下载匹配的timezlrg.dat和timezone.dat(从 My Oracle Support 文档 ID 412151.1 获取),替换 $ORACLE_HOME/oracore/zoneinfo/ 下对应文件,重启数据库实例 - 重启后再次查
v$timezone_file,确保VERSION已更新;此时再执行DBMS_DST.BEGIN_PREPARE才可能成功
为什么 DBMS_DST 的 PREPARE 阶段总卡住或返回 0 行冲突
prepare 不是“一键修复”,它只扫描含 TIMESTAMP WITH TIME ZONE 列的表,并检查这些列中是否存在“无法自动迁移”的时区数据(比如用了已废弃的缩写如 ‘PST’ 而非 ‘America/Los_Angeles’)。返回 0 行不代表没问题,而是没找到可识别的冲突模式——但实际可能有隐性风险。
- 必须确保数据库处于
OPEN状态且未开启任何DBMS_DST操作(查DBA_DST_TAB是否为空) - 如果表里存的是字符串型时区(如
VARCHAR2存 ‘GMT+8’),DBMS_DST完全无视——它只认 Oracle 原生TIMESTAMP WITH TIME ZONE类型 - 某些分区表、IOT 表或含虚拟列的表可能被跳过,需单独验证;建议用
SELECT OWNER, TABLE_NAME, COLUMN_NAME FROM DBA_TAB_COLUMNS WHERE DATA_TYPE = 'TIMESTAMP WITH TIME ZONE';手动核对范围 - prepare 后务必查
DBA_DST_TAB:若PROCESSING_WINDOW为 NULL,说明该表未被纳入扫描,不是漏了就是类型不匹配
打 Timezone Patch 时 DBMS_DST 提示 ORA-56925 怎么处理
ORA-56925: end of DST patch operation failed 多半发生在 END_UPGRADE 阶段,本质是升级过程中某张表的时区数据校验失败,但 Oracle 不告诉你哪张表、哪行数据——它只回滚整个操作并锁死后续调用。
- 立刻查
DBA_DST_TAB中UPGRADE_STATE为DETECTED或INTERVAL的记录,这些是已识别但未处理的表 - 对每张问题表,手动运行:
SELECT COUNT(*) FROM <owner>.<table> WHERE <tztz_column> IS NOT NULL AND EXTRACT(YEAR FROM <tztz_column>) —— 老旧年份(尤其 1900 年前)极易触发校验失败<li>临时方案:用 <code>DBMS_DST.UNLOAD_SECONDARY清空二级时区信息(慎用,仅限测试库),或导出问题数据、转成TIMESTAMP再重载 - 补丁包本身不能跳过校验,官方不提供“强制升级”开关;想绕过只能降级时区文件版本(不推荐生产环境)
- 自动机制只影响新插入的数据和系统函数(如
SYSTIMESTAMP),不影响已有行 - 查看是否启用:
SELECT PROPERTY_NAME, PROPERTY_VALUE FROM DATABASE_PROPERTIES WHERE PROPERTY_NAME = 'DST_PRIMARY_TT_VERSION';—— 若值为空或远低于v$timezone_file.VERSION,说明自动机制未生效 - 即使启用了自动机制,每次打 timezone patch 后仍需人工执行完整
DBMS_DST流程,否则DBA_HIST_SNAPSHOT等 AWR 表里的时区字段会持续偏差 - 19c 引入
DBMS_DST.UPGRADE_DATABASE一步到位,但它内部仍是分 prepare → upgrade → end_upgrade 三步走,只是封装了——出错时你还是得回到各阶段日志里翻细节
Oracle 12c 及以后版本是否还必须手动跑 DBMS_DST
12c 起引入了自动时区更新机制(Auto DST Update),但仅适用于 Oracle 自身发布的 timezone patch,不覆盖用户自定义时区规则或历史数据修正。也就是说:数据库能自动加载新 timezlrg.dat,但存量 TIMESTAMP WITH TIME ZONE 数据仍需 DBMS_DST 显式迁移。
真正麻烦的从来不是命令怎么敲,而是哪些表被漏扫、哪些数据年份太老、哪些路径下的 timezlrg.dat 被误替换了却没重启实例。查 v$timezone_file 和 DBA_DST_TAB 这两处,比反复重跑 BEGIN_PREPARE 有用得多。










