必须在旧库上运行preupgrade.jar,因其能检测DBUA遗漏的语义级兼容问题(如SEC_CASE_SENSITIVE_LOGON废弃)、需用源库JDK、OPEN状态执行,并严格检查ERROR项(INVALID对象、时区版本、目录权限等)。
必须在旧库上运行 preupgrade.jar,不是可选项,也不是 dbua 自带检查能替代的。
为什么 preupgrade.jar 不能跳过或用 DBUA 替代
DBUA 的预检只做基础连通性、空间、权限扫描,漏掉大量语义级兼容问题。比如 SEC_CASE_SENSITIVE_LOGON 在 11g 是默认开启的参数,但 12c+ 已废弃;不处理会导致升级后所有密码登录失败。而 preupgrade.jar 会明确标出这一项为 ERROR,并生成修复脚本。
- 必须用源库(如 11.2.0.4)自带的
java运行,不能用 19c 的 JDK,否则类加载失败或检查逻辑错位 - 必须在数据库
OPEN状态下执行,否则无法读取DBA_REGISTRY、DBA_OBJECTS等动态视图 - 输出的
preupgrade.log和preupgrade_fixups.sql要逐行确认,尤其盯住 “ERROR” 级别项(如 INVALID objects、timezone mismatch、directory privilege loss)
执行 preupgrade.jar 的标准命令和路径注意点
命令本身简单,但路径写错就直接报 ClassNotFoundException 或静默失败:
- 进入 11g 的
$ORACLE_HOME/rdbms/admin/目录下执行,不是 19c 的目录 - 命令示例:
java -jar preupgrade.jar FILE TEXT DIR /tmp/preup—— 其中DIR /tmp/preup必须是 oracle 用户有读写权限的空目录,不能是/tmp根下已存在的非空目录 - 若提示
Could not find or load main class,先检查当前路径是否真在preupgrade.jar所在目录,再确认java -version输出的是 11g 自带的 JDK(通常为 1.6.x 或 1.7.x)
常见 ERROR 级别问题及对应动作
预检报告里真正要拦停升级的,往往就这三类:
-
Database contains INVALID objects:DBUA 不会自动编译,必须手动运行@?/rdbms/admin/utlrp.sql,且要等全部完成(查SELECT COUNT(*) FROM dba_objects WHERE status != 'VALID';返回 0) -
Timezone file version mismatch:11g 默认 v4,19c 要 v32+,得在 11g 库中提前执行@?/rdbms/admin/utltzuv2.sql,否则升级后SYSTIMESTAMP计算偏移错误 -
Directory object privileges:19c 对CREATE ANY DIRECTORY权限校验更严,若用过 Data Pump,需确认对应 directory 的GRANT READ,WRITE ON DIRECTORY ...是否仍有效,否则 expdp/impdp 失败
字符集 AL32UTF8 并不等于安全
看着都是 AL32UTF8,但 11g 基于 Unicode 5.0,19c 升级到 Unicode 13.0。某些增补汉字(如「?」「?」)、emoji(如 ?)在升级后可能变乱码或触发 ORA-12899(value too large for column)。
- 不能只看
NLS_CHARACTERSET值相同就跳过检查 - 真正验证方式是用 11g 的
csscan扫描全库,再用 19c 的csalter.plb模拟转换,比对结果差异 - 如果扫描发现高风险字符,要么提前清理,要么接受升级后部分字段截断或报错
预检不是走流程,而是把升级失败点提前暴露出来。很多人卡在 DBUA 白屏或中途报错,回头翻日志才发现是 preupgrade.jar 早标出的 ERROR 被忽略了——尤其是时区文件版本和无效对象这两项,最容易被当成警告跳过。


















