简介:面向具备一定运维能力的数据库管理员,这份 Oracle 11g 升级至 19C 的实务手册围绕 DBUA 工具展开,重点解决生产库迁移中的版本兼容、备份恢复与升级风险控制问题。全包仅 1 个 PDF 文件,约 3.18MB,篇幅集中、便于随查随用。内容覆盖前期 RMAN 备份与异机恢复、DBUA 图形化及静默升级流程、必要参数调整,并提醒逐项核对检查脚本输出的日志与警告;同时给出 MOS 参考文档、直升级与间接升级路线、操作系统版本要求及多种异常处置思路。已有 1360 人学习,适合希望安全完成 11g 到 19C 迁移、提升性能与安全合规性的运维人员对照实践和排错复盘。
1. 从 11.2.0.4 到 19.14:先判断这条路能不能一步走完
凌晨收到一条通知,一套还在跑 11.2.0.4 的单机库不再有补丁,而新机器上 19.14 的软件已经装好。Oracle 11g 到 19C 的升级,用 DBUA 点几下确实能走完,真正卡住人的从来不是向导界面,而是点之前的三件事:源库版本能不能直连 19C、主机是不是 Linux 7 以上、备份能不能在升级机上按时间点恢复出来。这份手册记录的是走通过的一条路径——生产库先用 RMAN 恢复到独立主机,只读验证无误后交给 DBUA 原地升级,源库原封不动留作回退。适合能进 SYSDBA、会写 RMAN 脚本、准备把老库迁到 19C 的运维,也适合想弄清 DBUA 每一步到底改了什么的人。
2. 升级前的硬性门槛:升级路线、主机版本与源库体检
2.1 先判路线:直连还是中转
11g 到 19C 不是所有小版本都能一步到位,这个判断做错了,后面所有准备工作都是白费。DBUA 在执行前的 precheck 阶段会直接读源库的v$instance和dba_registry,版本不在直连清单里就会拒绝继续,不会给你“强行升级”的选项。
| 源库版本 | 到 19C 的路径 | 说明 |
|---|---|---|
| 11.2.0.4 及以上 | 直接升级 | 主流路径,DBUA 直接支持 |
| 11.2.0.1 / 11.2.0.2 / 11.2.0.3 | 先补到 11.2.0.4,再升 19C | 差一个补丁集,必须先打 |
| 11.1.0.6 / 11.1.0.7 | 先到 11.2.0.4 | 跨两个大版本 |
| 10.2.0.2 ~ 10.2.0.5 | 经 11.2.0.4 或 12.1.0.2 中转 | 中转版本决定后续脚本差异 |
| 12.1.0.1 | 经 12.1.0.2 或 12.2.0.1 | 12.1.0.1 不在直连清单 |
| 12.1.0.2 / 12.2.0.1 / 18c | 直接升级 | 与 11.2.0.4 同路径 |
表里最容易误判的是 11.2.0.1 到 11.2.0.3。很多环境自报“11.2.0.4”,实际opatch lspatches里只有 PSU 没有基版升级,v$instance.version还是 11.2.0.3。判断依据统一看select version, version_full from v$instance;,别看安装介质的目录名。
2.2 主机版本:Linux 6 上的库必须换机
19C 对操作系统的最低要求是 Linux 7(RHEL 或同源发行版 7 及以上)。11g 时代大量库跑在 RHEL 6 上,19C 的安装介质在那上面根本装不起来,这不是打补丁能解决的。先cat /etc/redhat-release看主版本号,是 6 就老老实实准备新机器,别在原地耗时间。
原地升级只在一种情况下成立:源库主机已经是 7 以上,并且同一台机器上可以并存两套 ORACLE_HOME。这种情况下升级的本质是“换 home 启动”,不是“换机器”,环境变量的隔离就成了头号问题。ORACLE_HOME、ORACLE_BASE、PATH、LD_LIBRARY_PATH一次只能指向一套,切 home 靠source不同的 profile 文件,不要靠临时 export 拼凑,否则 DBUA 会读到错误的oratab和错误的dbua可执行文件。
两套 home 并存还要处理监听。19C 的监听用 19C home 下的lsnrctl启动,11g 的监听在升级窗口内停掉,/etc/oratab里两个 SID 的条目都要保留,DBUA 依靠它识别源库版本。端口不要复用,11g 监听占 1521,19C 监听可以先用 1522,升级完成后再切回,避免升级期间应用误连到正在被 DBUA 重启的实例。
2.3 用 preupgrade 脚本把源库的雷提前排掉
DBUA 自带 precheck,但它只告诉你“不行”,不告诉你“怎么修”。真正干活的是 preupgrade 脚本,它会在源库上做一次全面体检,并生成可以自动修复的 SQL 脚本。
# 在源库所在主机执行,preupgrade.jar 从 19C 的 $ORACLE_HOME/rdbms/admin 目录拷贝过来 export ORACLE_SID=PRODDB export ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1 export PATH=$ORACLE_HOME/bin:$PATH # 11.2.0.4 自带 jdk 1.6/1.7,能直接跑 jar $ORACLE_HOME/jdk/bin/java -version # TERMINAL 输出到终端,TEXT 生成文本报告而不是 HTML mkdir -p /home/oracle/preupgrade cd /home/oracle/preupgrade $ORACLE_HOME/jdk/bin/java -jar /home/oracle/preupgrade.jar \ TERMINAL TEXT \ > /home/oracle/preupgrade/preupgrade_stdout.log 2>&1这段命令的逻辑很直接:用源库自己的 JDK 跑 19C 提供的检查包,避免 Java 版本不兼容导致脚本静默失败。TERMINAL TEXT两个参数分别控制输出目标和格式,只写TERMINAL会走交互式终端,只写TEXT会生成文件但不在屏幕提示,两个一起写才是“屏幕看得见 + 文件留得下”。执行完之后产物在$ORACLE_BASE/cfgtoollogs/<sid>/preupgrade/下,一共三个文件:preupgrade.log是体检报告,preupgrade_fixups.sql要在源库上执行,postupgrade_fixups.sql留到升级之后。
体检报告要用眼睛过一遍,不能只看最后一行“建议升级”。几个必须自己复核的项:
-- 组件状态,任何一行不是 VALID 都要先处理,DBUA 会因此拒绝升级 SELECT comp_id, comp_name, version, status FROM dba_registry ORDER BY comp_id; -- 时区文件版本,19C 常见需要 DSTv32 SELECT version FROM v$timezone_file; -- 无效对象,升级前应该接近 0 SELECT owner, object_type, COUNT(*) FROM dba_objects WHERE status = 'INVALID' GROUP BY owner, object_type ORDER BY 3 DESC; -- 只读表空间和脱机数据文件,升级期间无法处理 SELECT tablespace_name, status FROM dba_tablespaces WHERE status <> 'ONLINE'; SELECT file#, name, status FROM v$datafile WHERE status <> 'ONLINE'; -- 字符集,跨字符集升级不属于 DBUA 的范畴 SELECT parameter, value FROM nls_database_parameters WHERE parameter IN ('NLS_CHARACTERSET','NLS_NCHAR_CHARACTERSET');dba_registry里status不是VALID是 precheck 最常见的拦路虎,XDB、OLS、JVM 这三个在 11g 上尤其容易留下半死不活的状态。处理原则是“卸载重装”而不是“手工改状态”:XDB 用?/rdbms/admin/catnoqm.sql卸载后catqm.sql重装,JVM 用catnojav.sql加catjava.sql。这些脚本会动数据字典,只在已经恢复出来的升级库上跑,不要碰生产。
只读表空间这一项经常被忽略。DBUA 升级时会尝试写字典和部分组件表,遇到只读表空间直接报错中断,alter tablespace ... read write之后记得在升级完成后改回去。
2.4 目标端 19C 软件安装的三个细节
19C 软件用 OUI 装,选 “Install software only”,不要顺手建库,否则会多出一个空实例干扰oratab判断。
第一个细节是用户组。oracle用户的主组必须是oinstall,附加组至少包含dba、oper,和 11g 侧完全一致。组不一致会导致 DBUA 切换 home 时权限不足,报一堆ORA-01031。
第二个细节是系统参数。19C 对nofile的要求比 11g 高,/etc/security/limits.conf里至少给到 65536;kernel.shmmax、kernel.shmmni、fs.aio-max-nr按 19C 的安装文档重新算,不要沿用 11g 机器上那份几年前的值。半导体现在很常见,/dev/shm太小会让memory_target启动直接失败。
第三个细节是oraInst.loc。装完 19C 跑root.sh时,如果机器上已经有 11g 的/etc/oraInst.loc,让它保持指向同一个 inventory 目录,不要被覆盖成新路径,否则opatch会找不到两套 home 的补丁信息。
3. 用 RMAN 把生产库搬到升级机:恢复链路怎么搭
3.1 参数文件:从 spfile 到 pfile 的路径重写
升级不在生产机上做,这是整条路径的核心决策。生产库保持原样,把备份恢复到一台装了 11g 和 19C 两套软件的升级机上,在升级机上用 11g home 把库拉起来,只读验证后再交给 DBUA。这样任何一步翻车,最坏结果只是升级机重来,生产库连重启都不需要。
恢复的第一步是把参数文件从备份里捞出来:
# 升级机上先切到 11g 环境,恢复动作全部由 11g home 完成 export ORACLE_SID=PRODDB export ORACLE_HOME=/u02/app/oracle/product/11.2.0/dbhome_1 export PATH=$ORACLE_HOME/bin:$PATH rman target /RMAN> startup nomount; RMAN> restore spfile from '/hisbak/spfile_PRODDB_20220830_40444.ora'; RMAN> exit; -- 用还原出来的 spfile 生成可编辑的 pfile SQL> create pfile='/home/oracle/pfile.ora' from spfile;startup nomount只需要参数文件就能起实例,所以这一步能在数据文件还没到位时先做。restore spfile from后面跟的是备份片路径,不是备份集编号,路径写错会报RMAN-06026,先用ls -l确认文件存在。
生成的 pfile 必须逐项改成本机路径,不能直接拿来启动:
# /home/oracle/pfile.ora 关键改动项,其余保持源库原值 *.audit_file_dest='/u02/app/oracle/admin/proddb/adump' *.control_files='/oradata/proddb/controlfile/control01.ctl' *.db_create_file_dest='/oradata' *.db_recovery_file_dest='/arch' *.db_recovery_file_dest_size=200G *.db_unique_name='PRODDB_UPG' *.diagnostic_dest='/u02/app/oracle' *.log_archive_dest_1='LOCATION=use_db_recovery_file_dest VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=PRODDB_UPG' *.log_archive_format='%t_%s_%r.dbf' *.memory_target=64G *.sga_target=32G *.pga_aggregate_target=8G *.processes=6000 *.sessions=3305db_unique_name必须和源库不同,否则归档命名和后续的 Data Guard 配置会撞车;db_name保持原值不动,DBUA 认的是db_name。内存三项是异地恢复最容易翻车的地方:源库 128G 的memory_target原样搬到 64G 的机器上,实例连 nomount 都过不去,报ORA-00845或直接 OOM。先按目标机物理内存的 60% 给,起来之后再调。
改完之后:
SQL> startup nomount pfile='/home/oracle/pfile.ora'; SQL> create spfile from pfile='/home/oracle/pfile.ora'; SQL> shutdown immediate; SQL> startup nomount;先 pfile 起、再固化 spfile、再重启,目的是让实例从默认的$ORACLE_HOME/dbs读 spfile,后面 DBUA 切 home 时不会因为找不到参数文件而失败。
3.2 控制文件、catalog 与数据文件重定位
参数文件就位后,控制文件是下一个关键入口。控制文件里记录了所有数据文件的绝对路径,这些路径在新机器上大概率不存在,所以顺序必须是“先还原控制文件 → mount → 加载备份 → 重定位 → 还原数据文件”。
RMAN> restore controlfile from '/hisbak/PRODDB_CONT_20220830_40443.ctl'; RMAN> sql 'alter database mount'; RMAN> catalog start with '/hisbak/'; RMAN> report schema;restore controlfile会自动把实例从 nomount 推进到 mount,不需要手动再 mount 一次,多写一条alter database mount会报ORA-01081。catalog start with把备份目录下所有备份片注册进控制文件,备份目录大、片子多的时候这一步会跑十几分钟,可以先用catalog start with '/hisbak/arch/'分批加载。
report schema的输出是重定位的依据。如果源库用的是 ASM,看到的全是+DATA/...这种路径,在新机器上必须全部替换:
RMAN> run { allocate channel c1 device type disk; allocate channel c2 device type disk; allocate channel c3 device type disk; allocate channel c4 device type disk; -- %b 保留原文件名,统一重定位到新目录 set newname for database to '/oradata/proddb/datafile/%b'; set until time "to_date('2022-08-30:02:00:00','yyyy-mm-dd:hh24:mi:ss')"; restore database; release channel c1; release channel c2; release channel c3; release channel c4; }通道数按目标机 CPU 和存储带宽定,4 到 8 个是常见区间,开太多会因为 IO 争抢反而更慢。%b只保留文件名不保留原目录,如果不同表空间下有同名文件(两个system01.dbf这种情况),restore会互相覆盖,这时改用%U生成唯一名,或者在set newname里按 datafile 号逐个指定。
set until time给了一个不完整恢复的时间点,这是有意为之——先把库拉到一个较早的、确定一致的时点,验证没问题之后再拿归档往前追。追不追、追到哪儿,主动权在自己手上。
还原完成后必须执行一次路径切换:
RMAN> switch database to copy;这条命令把控制文件里记录的数据文件路径真正改写成set newname指定的新路径。少这一步,后面的recover会去源库的老路径找文件,报ORA-01189或ORA-01119。
3.3 只读打开与追归档:把恢复时间点往前推
第一轮恢复之后,库还不能直接给 DBUA。先recover到一个业务低峰时点,再只读打开做数据校验:
RMAN> run { allocate channel c1 device type disk; allocate channel c2 device type disk; allocate channel c3 device type disk; allocate channel c4 device type disk; set until time "to_date('2022-08-30:07:00:00','yyyy-mm-dd:hh24:mi:ss')"; recover database; release channel c1; release channel c2; release channel c3; release channel c4; }recover完成后再打开:
SQL> alter database open read only; SQL> select count(*) from v$datafile; SQL> select file#, checkpoint_change# from v$datafile_header; SQL> select count(*) from <业务核心表>;只读打开的目的是让业务方连上来核对数据,读数对不上说明恢复链路有问题,这时候停下来查归档比升级完再查便宜得多。只读状态下库不能被 recover,想继续往前追必须先关掉:
SQL> shutdown abort; SQL> startup mount;然后从源库把新产生的归档拷过来,重新 catalog 再 recover:
# 源库侧持续拷贝归档,rsync 只传增量 rsync -avz /arch/ PRODDB@10.10.10.21:/hisbak/arch/RMAN> catalog start with '/hisbak/arch/'; RMAN> run { allocate channel c1 device type disk; allocate channel c2 device type disk; set until time "to_date('2022-08-30:12:00:00','yyyy-mm-dd:hh24:mi:ss')"; recover database; release channel c1; release channel c2; }不指定until time时 RMAN 会一直追到归档尽头,然后报RMAN-06054: media recovery requesting unknown archived log。这个报错不是失败,它只是在说“归档不够了”,属于预期行为,看到它就可以停手。真正的失败是RMAN-06054之前出现ORA-开头的错误,那才需要查。
追到哪个时间点停?我一般追到源库业务停写、进入维护窗口的那一刻为止,把它作为最终恢复点。这样升级完成后切换过去,丢失的数据窗口就是维护窗口本身,业务方容易接受。
4. DBUA 实操:从 precheck 到 postupgrade
4.1 升级前最后一公里的准备
库恢复好、只读验证通过之后,把它切成可读写但不接业务的状态,这是 DBUA 的起点。
/etc/oratab里这个 SID 的 home 必须还指向 11g,DBUA 依靠它判断“源库是 11.2.0.4,目标 home 是 19C”。如果之前手工改成了 19C,DBUA 会认为没有可升级的源库,列表里空空如也。
口令文件要提前处理。19C 从 12c 起换了口令文件格式,11g 的orapwPRODDB在 19C 下能读但哈希算法不一致,远程 sysdba 登录会遇到ORA-01017。做法是在升级前用 19C 的orapwd重建一次:
export ORACLE_HOME=/u01/app/oracle/product/19.14.0/dbhome_1 # format=12 生成 12c 及以上格式,19C 必须用这个;entries 给 sys/system 和几个 dba 账户留位置 $ORACLE_HOME/bin/orapwd file=$ORACLE_HOME/dbs/orapwPRODDB \ password='<sys密码>' entries=10 format=12此时实例还在用 11g home 运行,往 19C home 的dbs目录写口令文件不影响它,DBUA 切换 home 后正好用上。这一步提前做掉,能省掉升级完成后一半的登录类报错。
启动 DBUA 之前的环境变量要一次性设置正确:
export ORACLE_SID=PRODDB export ORACLE_HOME=/u01/app/oracle/product/19.14.0/dbhome_1 export ORACLE_BASE=/u01/app/or <p> <a href="https://download.csdn.net/download/u010575833/89885829" style="color:#ec7500;font-size:14px;"> 本文还有配套的精品资源,点击获取 </a> <img alt="menu-r.4af5f7ec.gif" src="https://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif" style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;"> </p>