滚动升级前必须确认data guard主库为primary/read write、备库为physical standby/mounted/managed real time apply,且主备均启用archivelog和force_logging;升级顺序为先升备库→switchover→再升原主库。
滚动升级前必须确认的 data guard 状态
滚动升级失败,八成卡在初始状态没对齐。不是所有 dg 配置都支持滚动升级——比如物理备库必须是实时应用(real-time apply)且主备库版本差不能跨两个大版本(如 19c → 23c 不行,但 19c → 21c 可行)。
执行前务必检查:
- 主库 SELECT DATABASE_ROLE, OPEN_MODE FROM V$DATABASE 必须是 PRIMARY 且 READ WRITE
- 备库 SELECT DATABASE_ROLE, OPEN_MODE, RECOVERY_MODE FROM V$DATABASE 必须是 PHYSICAL STANDBY、MOUNTED、MANAGED REAL TIME APPLY
- 主备库 SELECT LOG_MODE, FORCE_LOGGING FROM V$DATABASE 均需为 ARCHIVELOG 和 YES
常见错误现象:ORA-16826: enabled state of the primary database is inconsistent with the enabled state of the standby database —— 本质是 Broker 配置未同步或手动启停过 Apply 进程,导致 Broker 元数据错乱。
升级顺序和切换节奏怎么卡准
滚动升级不是“先升主再升备”,而是“先升备库 → 切换角色 → 再升原主库”。整个过程依赖一次 Switchover,不是 Failover。一旦用错命令,DG 关系就断了。
- 升级前停掉所有
DG Broker监控(DGMGRL中DISABLE CONFIGURATION),避免 Broker 自动干预 Switchover - 备库升级后,必须用
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL停应用,再STARTUP UPGRADE,否则catctl.pl会报ORA-01092: ORACLE instance terminated - Switchover 命令必须用 SQL*Plus 执行:先在原主库运行
ALTER DATABASE COMMIT TO SWITCHOVER TO STANDBY WITH SESSION SHUTDOWN,再在原备库运行ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY——DGMGRL SWITCHOVER在滚动升级中不可靠,尤其跨平台或补丁级别不一致时
升级脚本执行时最关键的三个参数
catctl.pl 是核心升级工具,但它默认并行度太高、日志太安静、超时太短,容易在大型库上假死或跳过关键步骤。
必须显式指定:
- -n 2:把并行进程压到 2 个以内,避免 shared pool 争用导致 ORA-04031
- -l /u01/app/oracle/cfgtoollogs/catupgrd/:强制指定独立日志路径,别用默认的 $ORACLE_HOME/rdbms/admin,否则升级中断后清理残留极麻烦
- -p 300:把每个组件超时设为 300 秒,防止因临时 latch 等待被误判失败
升级完成后,立刻在新主库运行:SELECT COMP_NAME, STATUS, VERSION FROM DBA_REGISTRY —— 如果出现 INVALID 或 LOADING,别急着切回,先查 $ORACLE_HOME/cfgtoollogs/catupgrd/catupgrd*.log 里最后 200 行,90% 的 INVALID 是 XML DB 或 ORDIM 组件因临时表空间不足挂起。
升级后 DG 同步突然变慢甚至中断
这不是网络问题,大概率是归档日志格式或传输参数没重配。19c 升 21c 后,默认启用 ARCHIVE_LAG_TARGET=0 和 LOG_ARCHIVE_DEST_n 的 SYNC 模式行为变化,导致 LGWR 进程频繁等待备库 ACK。
检查并调整:
- 新主库上确认 LOG_ARCHIVE_DEST_2(指向原主库)是否仍带 SYNC 属性,改成 ASYNC 更稳
- 备库(现为 standby)的 LOG_ARCHIVE_CONFIG 必须包含新主库的 DB_UNIQUE_NAME,否则 ALTER SYSTEM SWITCH LOGFILE 后日志根本传不出去
- SELECT DEST_ID, STATUS, TRANSMIT_MODE, AFFIRM FROM V$ARCHIVE_DEST WHERE DEST_ID = 2,如果 STATUS 是 INACTIVE,八成是 LOG_ARCHIVE_DEST_STATE_2=DEFER 没手动打开
最容易被忽略的是:升级后首次 ALTER SYSTEM SWITCH LOGFILE,必须在新主库执行两次 —— 第一次触发归档生成,第二次才真正把日志推给备库。只切一次,备库永远收不到第一组归档。










