Oracle 11g 升级 19C 实战:DBUA 与 RMAN 恢复避坑指南
简介:面向具备一定运维能力的数据库管理员(DBA)的实操型升级手册,围绕使用 DBUA 工具将 Oracle 11g 单机库迁移至 19C 这一典型场景展开,重点解决旧版本停止补丁更新后如何安全升级、如何控制回退风险的问题。内容涵盖升级路线与主机版本要求说明、前期 RMAN 备份并恢复到目标库时的参数文件调整、DBUA 图形与静默两种执行方式、升级后必要的配置修改,并附有 MOS 参考文档编号与多个故障处理方案,强调逐步核对脚本生成的日志与警告信息。资源包共 1 个 PDF 文件,约 3.18MB,单个文件即完整手册,便于离线查阅与打印对照。已有 1361 人学习下载,适合作为升级前评估与现场操作的参照,帮助读者理清从备份、恢复到升级验证的完整链路,降低迁移过程中的试错成本。
1. 版本账先算清楚:11.2.0.4 是直升级 19C 的唯一起点
上周帮人看一台要升级的 11.2.0.4 单机库,对方已经把 19C 软件装好,DBUA 也点到了第三步,结果卡在预检查那页不动。翻日志才发现源库 COMPATIBLE 参数还停在 11.2.0.3,升级脚本连组件校验都过不去。这类情况在 11g 到 19C 的路上特别多,因为中间跨了 12.1、12.2、18 三个大版本,官方允许直接升到 19C 的源库只有 11.2.0.4 及以上;11.2.0.1 到 11.2.0.3、11.1.0.6/11.1.0.7、10.2 全系、9.2.0.8 及更早,都得先补到 11.2.0.4 或 12.1.0.2 再走第二跳。正在做数据库升级、准备用 DBUA 图形化那条路把 Oracle 11g 升到 19C 的人,先把版本账、主机账、回退账算清,后面每一步才不会白跑。
2. 目标环境落地:RHEL 7.9 上装 19.14 并隔离两个 ORACLE_HOME
源库是生产环境,不能拿它做升级试验。稳妥的做法是另备一台机器装 19C 软件,把生产库的 RMAN 备份恢复过来,在副本上把升级跑通,生产库原样留着当后悔药。这次的环境是这样:源库 11.2.0.4 单机,目标机装 RHEL 7.9、19C 软件版本 19.14.0.0.220118。两个 ORACLE_HOME 我刻意放在不同挂载点,19C 在/u01/app/oracle/product/19.14.0/db_1,11g 那份留在/u02/app/oracle/product/11.2.0/db,回退时互不干扰。
| 角色 | 主机系统 | 主机名 | 数据库版本 | ORACLE_HOME |
|---|---|---|---|---|
| 源库(生产) | RHEL 7.9 | erpdb01 | 11.2.0.4.201020 (31537677) | /u02/app/oracle/product/11.2.0/db |
| 升级库(目标) | RHEL 7.9 | oracle19c | 19.14.0.0.220118 | /u01/app/oracle/product/19.14.0/db_1 |
提示:文中的库名、主机名、备份文件名都做过脱敏替换,路径结构保持一致,照着自己环境替换即可。
2.1 操作系统与内存的最低门槛
19C 对操作系统的要求比 11g 硬得多,最低是 Linux 7。如果源库主机还跑在 Linux 6 上,DBUA 那条路在物理上就不成立,必须先准备一台 Linux 7 的新机,把库搬过去再升。这一条不满足,后面所有步骤都是空谈。装机前我一般先跑一遍体检命令,把版本、内核、内存、挂载点余量一次性看清楚。
# 系统与资源体检,装 19C 前必看 cat /etc/redhat-release # 必须是 7.x 及以上 uname -r # 3.10.0-1160 这类内核较稳 free -g # 物理内存,对照 pfile 里的 SGA/PGA 预留 df -h /u01 /u02 /oradata /arch # 软件、数据、归档三个挂载点都要留足 grep -E 'memlock|nofile|nproc' /etc/security/limits.conf命令本身不复杂,关键是看返回值怎么判断。free -g那一列要能覆盖从生产带过来的sga_max_size和pga_aggregate_target之和,这台环境的 pfile 里sga_max_size是 64G、memory_max_target是 120G,目标机物理内存低于 128G 就要在参数文件里往下调,否则startup nomount直接报 ORA-27102 内存不够,升级还没开始就先翻车。df -h看的是/arch,DBUA 跑升级期间归档量会明显上涨,db_recovery_file_dest_size该给的余量不能抠;我吃过一次归档空间打满导致升级卡在 92% 的亏,后面每次都会把它单列出来核一遍。
2.2 19C 软件静默安装与两个 HOME 的隔离
19C 只装软件、不建库,用响应文件静默装最省事。软件清单里选INSTALL_DB_SWONLY,路径指到/u01/app/oracle/product/19.14.0/db_1,ORACLE_BASE统一到/u01/app/oracle。这里有个容易写错的地方:ORACLE_HOME的父目录必须能对上ORACLE_BASE,两者混写会让 root.sh 跑到一半报目录权限异常。
# 19c_swonly.rsp 关键片段 oracle.install.option=INSTALL_DB_SWONLY UNIX_GROUP_NAME=oinstall INVENTORY_LOCATION=/u01/app/oraInventory ORACLE_HOME=/u01/app/oracle/product/19.14.0/db_1 ORACLE_BASE=/u01/app/oracle oracle.install.db.InstallEdition=EE oracle.install.db.OSDBA_GROUP=dba oracle.install.db.OSOPER_GROUP=oper oracle.install.db.OSBACKUPDBA_GROUP=dba oracle.install.db.OSDGDBA_GROUP=dba oracle.install.db.OSKMDBA_GROUP=dba oracle.install.db.OSRACDBA_GROUP=dba各参数的作用:INSTALL_DB_SWONLY决定了只铺二进制、建库留给后面的 DBUA;OSDBA_GROUP这几个组要和系统里id oracle的结果完全一致,写成dba而实际组名是oracle之类,安装到最后一步会因组成员校验失败而回滚;INVENTORY_LOCATION建议单独放一层,避免和 11g 的清单目录混用,两个 home 共用一个 oraInventory 在打补丁时容易互相牵制。
执行安装同样是一条命令,跑完再用 root 执行脚本:
# 静默安装 19C 软件 /u01/app/oracle/product/19.14.0/db_1/runInstaller -silent -waitforcompletion \ -responseFile /home/oracle/19c_swonly.rsp -ignorePrereqFailure # 装完后用 root 跑一次,两个脚本都别落下 /u01/app/oraInventory/orainstRoot.sh /u01/app/oracle/product/19.14.0/db_1/root.sh-waitforcompletion让命令前台等结束,方便看返回码;-ignorePrereqFailure只在明确知道缺哪个包、并且准备装完立刻补的情况下才用,生产机上我一般不加,宁可先补包。装完不要急着往下走,先确认 19C 的$ORACLE_HOME/bin/sqlplus能起来、opatch lspatches能读出补丁列表,说明 home 是健康的。
2.3 升级前检查脚本:preupgrade.jar 与 dbupgdiag.sql
19C 已经不推utlu112i.sql那套了,正式检查用目标 home 里自带的preupgrade.jar,在源库上跑。它会输出三份东西:一份问题清单、一份升级前 fixup 脚本、一份升级后 fixup 脚本。我一般先跑TEXT模式看结论,确认没有致命项再往下走。
# 在源库执行,JDK 用 19c home 自带的,避免版本不匹配 cd /home/oracle $ORACLE_HOME/jdk/bin/java -jar $ORACLE_HOME/rdbms/admin/preupgrade.jar TEXT # 同时在源库收集字典健康信息,出问题时这是关键证据 sqlplus -S / as sysdba @?/rdbms/admin/dbupgdiag.sqlpreupgrade.jar的输出默认落在$ORACLE_BASE/cfgtoollogs/<SID>/preupgrade/下,里面有preupgrade.log、preupgrade_fixups.sql、postupgrade_fixups.sql三个文件。日志里要重点盯三类:COMPATIBLE参数是否满足、DBA_REGISTRY里有没有非 VALID 的组件、时区文件版本是否落后。dbupgdiag.sql生成的是字典诊断报告,升级失败时提交问题基本都要靠它,先跑一遍存着不亏。
preupgrade_fixups.sql在源库执行,postupgrade_fixups.sql留到升级完再跑,这两个别弄反。执行前把库开成 RESTRICTED 会话模式,避免业务连接在改对象时插进来。
-- 升级前固定动作:干净关机、清回收站、编译无效对象 shutdown immediate; startup restrict; purge dba_recyclebin; @?/rdbms/admin/utlrp.sql select count(*) from dba_objects where status = 'INVALID';purge dba_recyclebin是为了避免回收站里的对象被升级脚本扫描到,utlrp.sql编译一遍无效对象,最后那条计数最好归零。做不到零也不用慌,但要知道剩的是哪些——如果集中在业务自建包上,升级后还要再编一次。
3. 把生产库搬过来:RMAN 恢复 spfile、控制文件与追归档
升级环境准备好之后,下一步是把生产库的数据弄过来。这一步用 RMAN 做,思路是"先恢复到某个较早的时间点,只要能起来,剩下的靠追归档往前推"。这样做的好处是:恢复阶段不用等生产库停机,升级窗口里只需要把最后一段归档拷过来追平,窗口能压得很短。库名这里用erp,唯一名用erpup,和源库区分开。
3.1 恢复参数文件与控制文件
第一步永远是参数文件。从备份里把 spfile 捞出来,转成 pfile 之后按目标机的实际情况改路径,再反向生成一份新的 spfile。这一步不改干净,后面startup mount一定报控制文件找不到。
# 起实例到 nomount,准备恢复 spfile [oracle@oracle19c:~]$ source .bash_profile [oracle@oracle19c:~]$ rman target / RMAN> startup nomount; RMAN> restore spfile from '/hisbak/spfile_ERPDB_562120512_20220830_40444.ora';-- 转 pfile 出来改路径,再生成新的 spfile SQL> create pfile='/home/oracle/pfile.ora' from spfile;pfile 里要动手的地方集中在路径类参数上,下面这几项是每次都要核的:
# /home/oracle/pfile.ora 关键项(其余略) *.db_name='erp' *.db_unique_name='erpup' *.audit_file_dest='/u02/app/oracle/admin/erp/adump' *.control_files='/oradata/erpup/controlfile/control01.dbf' *.db_create_file_dest='/oradata' *.db_recovery_file_dest='/arch' *.db_recovery_file_dest_size=200G *.diagnostic_dest='/u02/app/oracle' *.sga_max_size=68719476736 *.sga_target=68719476736 *.pga_aggregate_target=8474591232 *.processes=6000 *.sessions=3305 *.undo_tablespace='UNDOTBS1' *.sec_case_sensitive_logon=FALSEdb_name保持和生产一致,db_unique_name换成新的,这样回退时两份库不会撞名;audit_file_dest、control_files、db_create_file_dest全部指向目标机的目录,原样照抄生产路径是最常见的错误,目录不存在时实例根本起不来。sga_max_size和pga_aggregate_target这两个值是从生产带过来的,目标机内存不够就按 2.1 节的判断往下调。
改完 pfile 之后建目录、起实例、生成新 spfile:
mkdir -p /u02/app/oracle/admin/erp/adump mkdir -p /oradata/erpup/controlfile/SQL> startup nomount pfile='/home/oracle/pfile.ora'; SQL> create spfile='/u02/app/oracle/product/11.2.0/db/dbs/spfileerp.ora' from pfile='/home/oracle/pfile.ora';注意这里生成的 spfile 放在 11g 那个 home 的dbs目录下,因为此刻实例还是 11.2.0.4 版本,必须用 11g 的二进制来启。19C 的 home 在这个时候只提供 DBUA 工具,不参与启库。
控制文件从备份集里恢复,恢复到哪一步是有讲究的:控制文件恢复出来的时间点决定了后面能追到多近,恢复完要立刻mount并catalog备份目录,让 RMAN 认识这些备份片。
[oracle@oracle19c:/hisbak]$ rman target / RMAN> restore controlfile from '/hisbak/ERPDB_CONT_562120512_20220830_40443.ctl'; RMAN> sql 'alter database mount'; RMAN> catalog start with '/hisbak/';restore controlfile之后实例处于 nomount,必须alter database mount才能看到数据文件列表;catalog start with是让 RMAN 把目录下所有备份片登记进来,不做这一步,后面的restore database会报找不到备份。这一步做完可以REPORT SCHEMA看一眼数据文件清单,确认文件数量和源库对得上。
3.2 restore 与 recover:把数据文件落到新路径
数据文件在备份里记的是源库路径,恢复时必须用SET NEWNAME重定向到目标机目录,否则会出现大批"文件已存在"或者"路径不存在"的报错。这次的目标路径是/oradata/ERPUP/datafile/%b,%b表示沿用原文件名,只换目录,可读性好。
# 多通道并行恢复,通道数按主机 CPU 和磁盘 IO 定,这里给 16 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; ALLOCATE CHANNEL C5 DEVICE TYPE DISK; ALLOCATE CHANNEL C6 DEVICE TYPE DISK; ALLOCATE CHANNEL C7 DEVICE TYPE DISK; ALLOCATE CHANNEL C8 DEVICE TYPE DISK; ALLOCATE CHANNEL C9 DEVICE TYPE DISK; ALLOCATE CHANNEL C10 DEVICE TYPE DISK; ALLOCATE CHANNEL C11 DEVICE TYPE DISK; ALLOCATE CHANNEL C12 DEVICE TYPE DISK; ALLOCATE CHANNEL C13 DEVICE TYPE DISK; ALLOCATE CHANNEL C14 DEVICE TYPE DISK; ALLOCATE CHANNEL C15 DEVICE TYPE DISK; ALLOCATE CHANNEL C16 DEVICE TYPE DISK; SET NEWNAME FOR DATABASE TO '/oradata/ERPUP/datafile/%b'; SET UNTIL TIME "TO_DATE('2022-08-30:02:00:00','YYYY-MM-DD:HH24:MI:SS')"; RESTORE DATABASE; RELEASE CHANNEL C16; RELEASE CHANNEL C1; }SET UNTIL TIME是这次恢复的时间边界,选一个比备份完成时间略早的点,保证数据文件是一致的;SET NEWNAME FOR DATABASE对所有数据文件生效,包括后来加的那些;通道数不是越多越好,16 个通道在普通 SAN 上已经接近带宽上限,再加只会互相抢 IO。恢复时间主要取决于备份片大小和磁盘吞吐,几十 G 的库一般几十分钟量级。
恢复完数据文件,用SWITCH DATABASE TO COPY把控制文件里的路径切到新位置,然后进入 recover 阶段。
rman target / SWITCH DATABASE TO COPY; 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; ALLOCATE CHANNEL C5 DEVICE TYPE DISK; ALLOCATE CHANNEL C6 DEVICE TYPE DISK; ALLOCATE CHANNEL C7 DEVICE TYPE DISK; ALLOCATE CHANNEL C8 DEVICE TYPE DISK; SET UNTIL TIME "TO_DATE('2022-08-30:07:00:00','YYYY-MM-DD:HH24:MI:SS')"; RECOVER DATABASE; RELEASE CHANNEL C8; RELEASE CHANNEL C1; }SWITCH DATABASE TO COPY不做的话,控制文件里记的还是生产路径,recover 会一直去找不存在的文件。recover 的时间点可以分段往前推,先到 07:00,再追到 12:00,每追一段都是增量应用归档,代价比一次性追到最新更可控——万一中间某段归档损坏,还能定位在哪一段断掉。
3.3 只读打开与继续追归档
恢复到一个候选时间点后,先用只读方式打开验证一下,这一步相当于试跑,出问题不影响数据文件。
SQL> alter database open read only;只读能打开,说明数据文件、控制文件、归档链在这一点是一致的。这时候可以连进去抽查几张核心表,行数和生产对得上,再决定要不要继续追。要再往前追归档,必须先关库回到 mount:
SQL> shutdown abort; SQL> startup mount;然后重新跑一次RECOVER DATABASE,不写SET UNTIL TIME就是把手上所有归档全部应用完,一直追到归档的尽头。追到底时会看到类似这样的报错:
RMAN-06054: media recovery requesting unknown archived log for thread 1 with sequence 25197 and starting SCN of 18157927920这条不是故障,是正常的"归档用完了"信号,说明手上能追的已经追到极限。要判断还差多少,用list backup of archivelog from time 'sysdate-1'看最后一段归档的序号和时间,再和源库当前的序号对一下,差得不多就可以准备升级了。真正做升级那天,把源库最后一段归档拷过来,recover一次追平,然后alter database open正常打开即可。
4. DBUA 执行升级:图形界面与静默模式的具体填法
DBUA 是 Oracle 自带的图形化升级工具,19C 里它承担的工作远比看上去多:跑预检查、调catupgrd.sql、升级时区、编译对象、注册监听、收集字典统计信息,全是它在后台驱动。官方那份升级检查清单(Doc ID 2545064.1)基本就是围绕它写的,静默方式另有一份(Doc ID 2548985.1)。这条路的好处是每一步都有日志,坏处是它不会替你做决定,前面欠的账全在预检查那页暴露。
4.1 启动 DBUA 前必须确认的四件事
DBUA 从 19C 的 home 启动,但操作的实例是 11g 的,环境变量必须同时指向两个方向,这一点最容易出错。启动前我固定核四件事:
第一,实例状态。库要处于OPEN或MOUNT,不能是 nomount,DBUA 连不上就报错退出。第二,环境变量。ORACLE_HOME指 19C,ORACLE_SID指源库,PATH里优先找 19C 的 bin,ORACLE_BASE指 19C 的 base。
# 启动 DBUA 前的环境变量,顺序不能反 export ORACLE_BASE=/u01/app/oracle export ORACLE_HOME=/u01/app/oracle/product/19.14.0/db_1 export ORACLE_SID=erp export PATH=$ORACLE_HOME/bin:$PATH export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH # 确认指向正确,别把 11g 的 sqlplus 拿起来 which sqlplus echo $ORACLE_HOME第三,监听。19C 的监听要么已经在跑,要么让 DBUA 自己起一个。如果沿用 11g 的监听配置,端口冲突、服务名注册错都会在升级最后一步暴露。第四,备份。升级前必须有一份完整的 RMAN 全备,加上 11g 那个 home 原样保留——回退全靠这两样,其他都是虚的。
4.2 图形界面:七个页面的实际选择
图形界面需要 X11 转发或者直接在控制台跑,dbua回车就起来。页面看着多,真正要动脑的只有几处。
第一页选要升级的实例,列表里出现多个 SID 时要看清是哪个,选错就等着出事。第二页是预检查,DBUA 会自动跑一遍,警告分两类:必须处理的会标红,建议处理的标黄,标红的必须先解决,否则下一步走不下去。第三页问要不要同时升级时区文件,默认选是——时区文件不跟着升,后续打补丁和DBMS_DST相关功能都会出问题,这个后面单独讲。第四页是并行度和日志路径,并行度按 CPU 核数给,别超过 16。第五页问是否启用 Oracle Enterprise Manager 和备份,这两项在生产机上我一般都不勾,升级时间会短不少。第六页是概要,把前面所有选择列一遍,逐行读一遍再点完成。最后一页是进度条,走完会给出成功或失败的结论。
图形化最容易忽略的是日志目录。DBUA 会在页面上显示日志路径,一般落在$ORACLE_BASE/cfgtoollogs/dbua/下,务必记下来。升级中途报错,第一个要看的就是这里,而不是界面上那句笼统的"升级失败"。
4.3 静默模式:一条 dbua 命令加一份日志
没有图形环境或者要写进脚本时,用静默模式。参数名以dbua -help的输出为准,不同小版本略有差异,常见的写法是这样:
# 静默升级,密码用引号包住防止特殊字符被 shell 吃掉 $ORACLE_HOME/bin/dbua -silent \ -sid erp \ -oracleHome /u01/app/oracle/product/19.14.0/db_1 \ -sysDBAUserName sys \ -sysDBAPassword 'YourPwd#2022' \ -timezone upgradeTimezoneFile-sid指定源库实例,-oracleHome是目标 home 的绝对路径,-sysDBAUserName和-sysDBAPassword给的是源库的 sys 口令,-timezone upgradeTimezoneFile表示同时升级时区文件。密码里带#、$、!这类字符,必须用单引号包住,否则会被 shell 解释成注释或者变量引用,DBUA 连不上库时报的是"密码错误",实际是密码被截断了——这种问题排查起来相当玄学。
静默模式没有交互界面,进度只能看日志,跑起来之后用tail -f盯住 DBUA 的日志文件,看到Database upgrade has been completed successfully才算完成。整个升级时长取决于库的大小和组件数量,几十 G 的库一般四十分钟到两小时,大库可能更久。
4.4 升级日志与警告的读法
DBUA 的日志分三层,看错层会白花时间。第一层是 DBUA 自己的日志,在$ORACLE_BASE/cfgtoollogs/dbua/下,记录每一步的调用和返回码;第二层是catupgrd.sql的执行日志,在$ORACLE_BASE/cfgtoollogs/catupgrd/下,升级脚本内部的报错全在这里;第三层是$ORACLE_HOME/rdbms/admin/下的各类.log,比如upgrade.log、catupgrd*.log。
# 升级跑完后,按错误级别快速过一遍日志 grep -iE 'ORA-|error|failed' $ORACLE_BASE/cfgtoollogs/dbua/erp/upgrade/*.log | head -50 ls -lt $ORACLE_BASE/cfgtoollogs/catupgrd/ | headORA-开头的错误要逐个看上下文,有些是升级脚本的预期行为(比如组件不存在时抛的 ORA-00942),有些是真正的阻断项。我的判断标准是:脚本最后有没有走到COMP_TIMESTAMP结束标记,有就是跑完了,过程中的 ORA- 大多是组件层面的可容忍报错;没有结束标记,就是中途断了,得从断点处查。
5. 升级避坑:DBUA 中途翻车的五类现场与救法
升级这件事,成功的路径只有一条,失败的姿势千奇百怪。下面这五类是我和身边同行实际撞过的,写清楚现象、原因和救法,遇到时能少绕两小时。
5.1 预检查卡在 COMPATIBLE 参数
现象:DBUA 第二页预检查转了很久,最后标红提示 COMPATIBLE 参数不满足要求,点下一步被拦住。原因:源库的compatible参数低于 11.2.0,19C 的升级脚本要求源库至少处于 11.2.0 兼容级别,因为很多新特性依赖这个基线。11.2.0.4 的库如果是从更早版本一路升上来的,这个参数常常还停在旧值没动过。
救法:在源库上确认当前值,再决定要不要调。
SQL> show parameter compatible; SQL> alter system set compatible='11.2.0.4' scope=spfile;改完必须重启实例生效,然后重跑 preupgrade。要注意的是compatible只能往高调不能往低调,调高之后 11g 里的某些降级特性就不能用了,生产库上动这个参数前要和业务确认。另外升级完成后这个参数还要再调一次到 19.0.0,但那一步不着急,等业务验证通过再动。
5.2 无效对象导致升级脚本中断
现象:DBUA 跑到一半退出,日志里出现大量ORA-04063: package body has errors或者ORA-06508。原因:源库里有非 VALID 状态的存储过程、包、视图,升级脚本在重新编译这些对象时失败,连带后续的组件升级也断了。11g 里长期不编译的对象、依赖了已删除表的视图,都是重灾区。
救法:升级前在源库把所有无效对象捞出来处理干净。
-- 升级前必做:列出无效对象并重编译 select owner, object_type, object_name from dba_objects where status = 'INVALID' order by 1,2,3; @?/rdbms/admin/utlrp.sql如果utlrp.sql跑完还有剩余,逐个看dba_errors里的具体错误。业务自建的包编译不过,要么改代码要么先删掉,别带着进 19C。升级后如果又出现无效对象,再跑一次utlrp.sql,正常会清干净。
5.3 时区文件没升导致后续补丁失败
现象:升级当时一切正常,过几个月打 RU 补丁时报时区版本不匹配,或者DBMS_DST相关查询报错。原因:DBUA 那页问"是否升级时区文件"时选了否,或者选了是但没等它跑完。11.2.0.4 的时区版本一般是 11 或 14,19.14 自带的是 32,差距这么大,应用层做时间运算迟早出问题。
救法:升级时那一步务必选是。如果已经漏了,事后单独补。
-- 检查当前时区版本 select version from v$timezone_file; -- 升级时区文件,需要停机 exec DBMS_DST.BEGIN_PREPARE(32); -- 中间跑 DBMS_DST 的 prepare 流程,检查受影响的行 exec DBMS_DST.END_PREPARE;时区升级涉及带TIMESTAMP WITH TIME ZONE列的表,数据量大的库要提前评估窗口。这件事拖得越久越麻烦,因为每来一次 RU,时区版本可能又往前走一版。
5.4 归档空间打满,DBUA 卡在 92%
现象:进度条走到九十多不动,日志里开始刷ORA-19809、ORA-00257归档空间不足。原因:升级过程中大量 DDL 产生归档,db_recovery_file_dest_size设得太保守,或者/arch这个挂载点本身快满了。这是纯血泪经验,升级前不查归档余量,等于给自己埋雷。
救法:升级前把db_recovery_file_dest_size调到实际需要的两三倍,并把/arch的可用空间核一遍。
SQL> show parameter db_recovery_file_dest_size; SQL> alter system set db_recovery_file_dest_size=500G scope=both; -- 顺手清一下过期归档,别在升级窗口里做 RMAN> delete noprompt archivelog until time 'sysdate-2';如果升级过程中已经卡住,先扩归档空间,DBUA 一般会自己继续往下跑;实在不动就重启 DBUA,它会从断点继续,但前提是前面那些步骤没有产生不一致状态。
5.5 升级失败想回退,11g 的 home 已经动过
现象:升级失败,想退回 11g,结果发现 11g 的 home 里被写过东西,startup报参数或组件版本异常,回不去了。原因:升级过程中有人顺手在 11g home 里跑了脚本,或者两个 home 共用了同一个dbs目录、同一个oratab,导致文件被覆盖。
救法:升级前给 11g 的 home 做一份目录级快照或者完整拷贝,oratab里把两个 home 的条目分开写清楚,升级期间不动 11g 的$ORACLE_HOME/dbs。真正回退靠的是升级前那份 RMAN 全备,不是靠现场修 home——修 home 这条路十次有九次修出别的问题。回退时的顺序是:关掉 19C 实例,用 11g 的二进制起实例,restore那份全备,把控制文件和数据文件一起回滚。
6. 升级后验收:一套判断是否真的跑通的检查清单
升级跑完,DBUA 报成功,不等于能交给业务。我的习惯是照着下面这套清单从头过一遍,全过了才允许切连接串。
-- 1. 版本与状态 select banner_full from v$version; select name, open_mode, log_mode from v$database; -- 2. 组件必须全部 VALID select comp_id, version, status from dba_registry order by 1; -- 3. 无效对象数量 select count(*) from dba_objects where status = 'INVALID'; -- 4. 时区版本 select version from v$timezone_file; -- 5. 归档与监听 archive log list;判断标准是这样一张表:
| 检查项 | 通过标准 | 不通过时先看哪 |
|---|---|---|
| 数据库版本 | 19.14.0.0.220118 | $ORACLE_HOME是否指错 |
| 组件状态 | 全部 VALID 或 OPTION OFF | catupgrd日志里对应组件段 |
| 无效对象 | 接近 0 | dba_errors逐条看 |
| 时区版本 | 32 | DBMS_DST流程是否走完 |
| 归档模式 | ARCHIVELOG | log_archive_dest参数 |
| 监听注册 | 服务名能连上 | lsnrctl status与service_names |
这套检查之外,我还会做两件事。一是抽查业务:挑三五张核心表,用select count(*)和源库最后追平的时间点对行数,再跑一两条典型查询看执行计划有没有异常膨胀——19C 的优化器行为和 11g 差别不小,个别执行计划会变,这是最容易被忽略的地方。二是看 AWR:升级后跑一个小时,对比升级前的 TOP 等待事件,如果出现明显的新型等待(比如大量library cache相关),说明有 SQL 在新版本上退化,得在切业务前处理掉。
postupgrade_fixups.sql别忘了在升级后的库上跑一遍,它会把 preupgrade 阶段记录的、需要升级后处理的事项一次性执行掉,包括权限回收、参数调整这些收尾工作。
从那以后我每次做升级,都会在正式窗口前先用这套清单在副本环境完整演练一遍,包括回退那一步也真跑一次——只在纸面上确认回退可行,和真的把库退回去,是两回事。希望帮到你。
本文还有配套的精品资源,点击获取