正德厚生,臻于至善

Oracle Data Guard 11g到19c切换避坑指南

一、为什么你的 Data Guard 切换总翻车?底层逻辑大揭秘

在讲怎么填坑之前,咱们先得明白坑是怎么来的。如果你连底层原理都没盘清楚,只会无脑复制粘贴代码,那生产出事是迟早的。

要知道,Switchover(平滑切换)和 Failover(故障切换)有本质区别。Failover 是破罐子破摔,主库挂了宕机了,备库强行接管,这种场景大概率会丢数据;而 Switchover 是一个极其优雅且严谨的“交接仪式”,讲究的是绝对的数据一致性、零丢失!

这个“交接仪式”从底层看,分两步走:

  1. 原主库降级(Switchover to Standby): 主库停掉所有针对数据文件的写入操作(发出 End of Redo 标记),把最后一批 Redo 和归档一股脑儿推给备库,然后在控制文件中记录角色的转换,最后自己乖乖变成 Physical Standby。
  2. 原备库升级(Switchover to Primary): 备库收到主库的 End of Redo 标记后,它的 MRP(Media Recovery Process)进程疯狂地消化这些日志。把所有收到的日志全都应用完(Apply),确认“一滴都不剩”了,备库的控制文件状态更新为 Primary,最后以 RESETLOGS 动作或 OPEN 动作打开,开放全业务的读写。

这中间的死穴在哪? 就是“干净”二字。 如果原主库还有活跃的事务(Active Transaction)咬着不放,或者在 RAC 环境下其他实例还在偷偷往里写;又或者网络抖动导致最后一个日志死活传不到备库……整个状态机就会卡在半空,也就是我们常说的“切成双备库”或者“挂在半边状态”。

从 V$DATABASE 的 DATABASE_ROLE 列来看,正常的状态流转是:

  • 节点A:PRIMARY -> TO STANDBY -> PHYSICAL STANDBY
  • 节点B:PHYSICAL STANDBY -> TO PRIMARY -> PRIMARY

如果你发现某个节点卡在 TO STANDBY 或者 TO PRIMARY,那恭喜你,你踩坑了!


二、切换前“保命”的六大绝招

⚠️ 避坑指南: 真正的高手,功夫都在诗外。切换翻车,80%是因为你准备工作做拉胯了!直接无脑敲 alter database commit to switchover...,不炸你炸谁?

在敲下任何切换命令前,请务必、一定、千万要在主备库分别跑一遍以下六大检查清单!

绝招一:确认传输与应用完全同步(杜绝缺档)

在主库和备库同时检查同步状态。如果这里不是零,哪怕差一秒,也绝对不要切!

# 备库上执行,通过自带的统计视图检查是否有传输挂起或应用延迟
SELECT NAME, VALUE, DATUM_TIME 
FROM V$DATAGUARD_STATS 
WHERE NAME IN ('transport lag', 'apply lag');

# 预期输出应该全都是 +00 00:00:00,表示完美同步

# 进一步核对:主库上执行,确认最后归档序号
SELECT THREAD#, MAX(SEQUENCE#) FROM V$ARCHIVED_LOG GROUP BY THREAD#;

# 备库上执行,核对是否都已经写入磁盘并被应用
SELECT THREAD#, MAX(SEQUENCE#) FROM V$ARCHIVED_LOG WHERE APPLIED='YES' GROUP BY THREAD#;

绝招二:排查主备库的 Standby Redo Log (SRL) 匹配度

好家伙,我见过太多平时跑得好好的,一切换发现新备库完全不同步的坑。为啥?很多新手建库跑 RMAN Duplicate 的时候,不管主库有没有配 Standby Redo Log。切过去之后,原主库(新备库)没有 SRL,无法接收实时日志,瞬间就报 Gap!

# 主备库两边都要执行:
SELECT GROUP#, THREAD#, BYTES/1024/1024 "SIZE(MB)", STATUS FROM V$STANDBY_LOG;
SELECT GROUP#, THREAD#, BYTES/1024/1024 "SIZE(MB)", STATUS FROM V$LOG;

铁律: SRL 的组数必须是 (最大在线日志组数 + 1) * 实例数,并且单组日志的 SIZE 必须和在线日志一模一样!没配的话立刻 ALTER DATABASE ADD STANDBY LOGFILE... 盖上去,绝不留患。

绝招三:确保没有”钉子户”会话或未决事务(专治 ORA-16060)

尤其是在带有 Active Data Guard (ADG) 选项的 12c-19c 环境下,备库是 Open Read Only 的。如果在跑大报表查询或者 ETL 抽取,只要持有锁或者长期占用 PGA 控制文件快照,切换命令立马会被锁死或超时退出。

# 备库抓取“钉子户”:重点揪出执行时间长、还在跑大运算的会话
# LAST_CALL_ET 能看到当前SQL跑了多少秒,EVENT 指示它在等什么资源状态
SELECT INST_ID, SID, SERIAL#, USERNAME, STATUS, SQL_ID, 
       LAST_CALL_ET AS "RUN_TIME_SEC",  -- SQL已经跑了多少秒,超过大几十秒的绝对是定时炸弹
       EVENT AS "WAIT_EVENT",           -- 正在等待的事件,判断是不是在大批量物理读盘
       STATE, SECONDS_IN_WAIT           -- 当前等待的时长
FROM GV$SESSION 
WHERE TYPE='USER' 
  AND STATUS='ACTIVE'
  AND LAST_CALL_ET > 60;  -- 经验值:过滤掉瞬时小查询,把霸占资源超过1分钟的大SQL精准揪出来

# 主库也要检查是否有未决分布式跨域事务
SELECT * FROM DBA_2PC_PENDING;

# 如果有分布式事务,一定要手工 rollback 掉或者 commit 掉

绝招四:检查 Temp 表空间文件的一致性

如果你在主库随时添加了 tempfile,很多时候这笔操作并不会在备库的 OS 层物理创建出来(受 standby_file_management 参数和文件路径转换规则影响)。如果临时文件没落盘,备库成功升级为 Primary 后,一旦连入业务跑大 SQL 需要做哈希排序,直接崩盘报 ORA-01157: cannot identify/lock data file!

# 备库查询当前临时文件状态:
SELECT FILE#, NAME, STATUS FROM V$TEMPFILE;
# 此时仔细核对:备库的 tempfile 数量和大小是否与主库完全一致?是否都处于 ONLINE 状态?

🚑 避坑与拯救手法: 如果你查出来发现备库的临时文件名字是乱码的(比如叫 UNNAMED000x),或者状态是 OFFLINE,甚至 OS 目录下根本没这个物理文件,不要慌,在备库直接手动加上去!

# 场景一:文件在 OS 层根本不存在,手动给当前的临时表空间追加一个
ALTER TABLESPACE TEMP ADD TEMPFILE '/u01/app/oracle/oradata/prod/temp02.dbf' SIZE 10G;

# 场景二:由于之前同步错误导致文件状态变为 OFFLINE,但其实不需要了,可以先干掉再加
ALTER DATABASE TEMPFILE '/u01/app/oracle/oradata/prod/temp01.dbf' DROP;
ALTER TABLESPACE TEMP ADD TEMPFILE '/u01/app/oracle/oradata/prod/temp01.dbf' SIZE 10G;

[打消疑虑:手动加 Tempfile 会弄断 Data Guard 同步吗?]绝对不会! 临时文件(Tempfile)不产生 Redo 日志,它纯粹是个运行时的消耗空间。你在备库(哪怕是处于 READ ONLY 的 ADG 模式,或者是 MOUNT 状态)手动进行 ADD TEMPFILE 或者 DROP TEMPFILE 的操作,完全不影响 MRP 进程的应用,也不会造成主备 SCN 的分叉。 切记,这是切换前排雷的零成本赚翻买卖,必须盘它!

绝招五:终极保险盒——创建保证还原点(GRP,救命稻草)

这也是笔者的“私房菜”。只要不丢数据,饭碗就能保住。建了 GRP,就算切出难以名状的状态甚至各类致命的内核级报错(比如控制文件角色转换断片的 ORA-00600: internal error code, arguments: [kcvfnc_1] 、日志应用断定失效的 ORA-00600: [kcvndl_1]),又或者是“两边都读着自己的日志、变成了双主库”的致命脑裂(Split-Brain),咱们也能底气十足地一键倒带!

# 在主库和备库上都需要操作(注意需要先配好归档空间并打开闪回)
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST_SIZE=100G SID='*';
ALTER DATABASE FLASHBACK ON;

# 创建保命点:
CREATE RESTORE POINT PRE_SWITCHOVER GUARANTEE FLASHBACK DATABASE;

# 验证效果
SELECT NAME, TIME, GUARANTEE_FLASHBACK_DATABASE FROM V$RESTORE_POINT;

有了这个 PRE_SWITCHOVER,你的底气能直接拉满。不用慌了!


三、11g-19c 切换核心报错与”救命”方案

进入咱们的重头戏实战高潮。当你敲下那句神圣的 alter database commit to switchover to physical standby;(11g)或者在 Broker 输入 switchover to dg_standby;(12c/19c)时,如果屏幕无情地甩出红字报错。不要慌,对号入座,来抄作业盘它!

1. 夺命催魂:ORA-16416 (Switchover target is not synchronized with the primary)

💣 踩坑场景: 这是最烂大街的报错。系统直白地告诉你:“老哥,主备不同步,切不了啊!” 🔍 核心原因: 存在归档日志断档(Archive Gap),或者 MRP 进程由于某种报错异常终止,很久没有应用日志了。

🚑 救命指南: 第一步,先去备库看一下到底哪丢了。

# 在备库查询GAP视图
SELECT * FROM V$ARCHIVE_GAP;

方案A 轻微延迟: 如果没查到 GAP,说明所有日志都有,只是还没应用完,请在备库再确认并拉起 MRP,然后等等就行。

ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;

方案B 中度断档,主库归档还在(比如刚才网络断了几个小时没传过来): 这是最好办的体力活。把 V$ARCHIVE_GAP 里查出来的缺失的那段归档日志,直接从主库手工拷贝到备库,然后让备库认领这批“失物”。

# 1. 去主库的归档目录下,把缺失的那几段日志通过 scp 手工拷到备库机器上,比如 /tmp/arch_gap/
scp /u01/arch/1_* oracle@standby_ip:/tmp/arch_gap/

# 2. 在备库上用 RMAN 将这些外来日志注册进控制文件
RMAN> CATALOG START WITH '/tmp/arch_gap/';

# 3. 注册完之后,重新拉起 MRP 应用进程,备库会自动顺着往下消化这批日志
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;

方案C 严重断档,主库归档已经被脚本清除了: 这是致命打击!既然日志没了,只能使用 RMAN 的“基于主库系统增量备份”跨步前滚法(Roll Forward Physical Standby)。

# 1. 在备库上查询当前的断层 SCN
SQL> SELECT CURRENT_SCN FROM V$DATABASE;  # 假设为 1888999

# 2. 回到主库上,只对超过这个 SCN 的块进行增量备份!
RMAN> BACKUP INCREMENTAL FROM SCN 1888999 DATABASE FORMAT '/tmp/ForStandby_%U' tag 'FORSTANDBY';
RMAN> BACKUP CURRENT CONTROLFILE FOR STANDBY FORMAT '/tmp/ForStandbyCtrl.bck';

# 3. 把这俩包 scp 到备库机器的 /tmp/ 下,并在备库恢复:
RMAN> CATALOG START WITH '/tmp/';
RMAN> RECOVER DATABASE NOREDO;

增量前滚搞定后,同步继续,再进行剩余的切换操作!


2. 拦路死硬派:ORA-16475 与 ORA-16060

💣 踩坑场景: 敲了 switchover 命令后卡半天,然后报错提示目标库仍在恢复中 (Target is either in recovery or has an active transaction) 或者 Switchover to standby not allowed。更绝望的是去看主库,主库可能已经半只脚踏进 Standby 大门了,进退两难。

🔍 核心原因:

  • 11g RAC 经典坑: 集群环境下的负载均衡或高可用进程(比如 VIP 还在上面),导致应用业务重连极快,其他实例没关干净。
  • 19c 经典坑: Active Data Guard 模式下引用的 19c 独有新特性 DML Redirection 留下了暗疮;在备库查表的同时,产生了一些临时内部写动作或者未释放的字典锁(Dictionary Lock)。此外还有很多兄弟在做 19c CDB/PDB 架构时,有个别 PDB 里的普通用户保持着超长生命周期的连接没有关闭。

🚑 救命指南: 对付此类问题,策略就是一个字——“杀”!但怎么杀才能既不断了数据库的核心进程,又能清空业务呢?

绝招: 在即将升级为 Primary 的机器(原备库端)执行以下终极降龙十八掌:

# 1. 尝试停止日志应用并主动释放部分会话
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;

# 2. 大面积清理普通连接(12c以上可用)
# 通过断开所有会话(除了SYS)来保证干净
ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;

# 3. 如果卡死无法执行,用最粗暴也最有效的方式重启该库到 mount
# 大忌:千万不要在这时候手贱用 shutdown abort!会把整个状态弄得更难以收场
SHUTDOWN IMMEDIATE; 
STARTUP MOUNT;

重启到 MOUNT 状态,相当于人为制造了一个物理隔离屏障。所有的用户会话进不来了,没有锁,绝对干净! 此时直接敲:

# 使用此招切换,神挡杀神
ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY WITH SESSION SHUTDOWN;

# 12c-19c 语法稍微简化了:
ALTER DATABASE SWITCHOVER TO <PRIMARY_UNIQUE_NAME> VERIFY;

3. 被遗忘的幽灵:ORA-16139 (media recovery required)

💣 踩坑场景: 想把处于 Mount 的备库原地提为 Primary,一敲命令立刻甩脸,报错 media recovery required。 🔍 核心原因: 很多人手动配置 Data Guard,用纯原生 SQL 命令。敲完主库变 Standby 之后,直接到备库敲强升命令,却忘了此刻备库的后台进程 MRP0 还在那吭哧吭哧刷着以前的日志不肯停!你得先让他停工交接,他还在打仗,你怎么宣战结束?

🚑 救命指南: 手写脚本或者原生命令的备库升主库,必须严格按下面四序操作,请把这四个动作融入肌肉记忆:

# 动作1:勒马停跑(取消 MRP 进程管理下的所有后台恢复)
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;

# 动作2:确认最后一批红移日志是否已经结清并拔高水线(如有必要)
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE FINISH;

# 动作3:真正的加冕仪式(转为主库属性)
ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY;

# 动作4:金库大开,迎接新流量(Open 数据库读写)
ALTER DATABASE OPEN;

4. 🧨 11.2.0.4 老古董专属巨坑:RAC 切机死锁与 ORA-01153

⚠️ 高危红色警报: 还在用 11g(特别是 11.2.0.4 和早期含 GI 的 12.1)的兄弟看过来!这个是臭名昭著的 Oracle 经典底bug(Bug号: 13083161)!

💣 踩坑场景: 两节点 RAC(节点1、节点2)当主库,单机版 Standby 当灾备。现在要把双节 RAC switchover 降下去。敲完命令后,会话直接死在那里不动,半小时没响应。在 alert 中出现大量死锁,或者报 ORA-01153 (an incompatible media recovery is active)。 🔍 核心原因: 在执行 switchover to physical standby 命令时,本该节点1广播全集群让节点2也把在线日志锁死准备降级。但这个该死的 Bug 导致 GCS/GES(全局锁管理及缓存管理)由于死锁不能正常关闭其他 RAC 实例!两边相互卡脖子。

🚑 救命指南与标准规范: 绝对不要在双节点以上全开的情况下发起主库降级!老哥教你万无一失的套路:

起飞前动作: 关掉除了你敲命令节点以外的所有实例!

# 在 Linux shell 层强行关闭 RAC 的第二个节点
srvctl stop instance -d ORCL_PRIMARY -i ORCL2

# 进到存活的节点 1
sqlplus / as sysdba

然后在单节点上发起“焦土式”降级切换,一定要加上参数后缀以杀死残留会话:

ALTER DATABASE COMMIT TO SWITCHOVER TO PHYSICAL STANDBY WITH SESSION SHUTDOWN;

# 降级完成后关库启动至 mount,这个时候你就可以把另一个节点按 standby 规矩正常挂载起来了
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;

5. 🧨 19c 专场陷阱:Broker (dgmgrl) 超时卡死 与 ORA-16625 / ORA-16619

从 12c 开始官方极力打压原生手工 SQL 切换,到处推 Data Guard Broker。所以现在大部分 19c 架构中,兄弟们应该都在用 Broker 控制台的 switchover to 目标库别名。 虽然一行代码搞定看起来很丝滑,但是 Broker 如果配不明白,一旦报错就是一大串连环杀,卡在进度条:ORA-16625 (cannot reach the database) 或 ORA-16619!

💣 踩坑原因:你到底有多不重视静态监听? 当 Broker 在执行切换时它的动作非常生猛。当你选择新主库时,Broker 内部会在远端执行 shutdown 并且尝试把它给重新 startup mount。如果你的系统只有依赖 PMON 自激注册的动态监听,当实例一关,动态监听立刻将其从监听列表中注销!Broker 下发 startup 的命令此刻发现网络里根本找不着实例,当场瞎了!连不上,超时,直接挂掉报 ORA-16625!

🚑 救命指南: 使用 Broker 的铁律命脉——必须为主备库每一侧的 listener.ora 手动且死死地写入静态注册信息。Broker 需要一个专用的 GLOBAL_DBNAME = xxx_DGMGRL 标记后缀,这样就算实例没有启动,监听端口也硬生生留个洞给 Broker 下发命令用。

# 文件路径 $ORACLE_HOME/network/admin/listener.ora 加上硬性代码
SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = PRODSTB_DGMGRL) # 这个 _DGMGRL 后缀是神来之笔,Broker专用!
      (ORACLE_HOME = /u01/app/oracle/product/19.3.0/dbhome_1)
      (SID_NAME = PROD)
    )
  )

配置完成后一定得敲一句 lsnrctl reload。没配妥这一条,在 19c 做 Broker Switchover 就是去摸高压电!


6. 网络与 OS 层面的隐形连环杀手:TNS-12152 与 ORA-03113

主备库一点毛病没有,参数完美,却在一切换最后关头,主备之间突然通信中断!在 alert 和 drc 日志中大量报 ORA-03113: end-of-file on communication channel 或者 TNS-12152: TNS:unable to send break message。

🔍 核心原因:原来“内鬼”在系统防火墙。 Data Guard 主备之间的 LNS、SYC 或者 ASYNC 进程跑的是长链接 Socket。但在很多大型生产环境中,操作系统层面使用了 iptables / firewalld 的 ip_conntrack 连接跟踪,或者中间过了深信服、绿盟的安全网关设备。当白天无业务交易没有日志传达时,连接就空闲在那。安全设备判定:这链接 10 分钟没心跳包流过了,掐断! 等到半夜零点你开始敲击回车发送最后切断的控制信令时,对面的链接早就物理断开几个小时了,Oracle 一头撞死在了 TNS 超时上。

🚑 救命指南(架构师级别的高阶网络调优):

  1. Oracle 层级的血管扩张术:DCD (Dead Connection Detection) 强制让 Oracle 进程每隔几分钟发一个小空包,穿透墙告诉网关“老子活着别砍长连接”。 在主备服务器的 $ORACLE_HOME/network/admin/sqlnet.ora 中都要加:
# 设置存活探测机制,每隔10分钟唤醒通信链路一波
SQLNET.EXPIRE_TIME = 10
  1. Linux 内核级防抖参数(双管齐下) 在 Linux 控制层面调整 TCP KeepAlive 保活:
# 用 root 用户修改 /etc/sysctl.conf
net.ipv4.tcp_keepalive_time = 600   # 修改心跳频率
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 5

# 执行生效
sysctl -p

加上这两道护身符,以后 Data Guard 绝对能告别这种幽灵般的网络突然暴毙。


7. 密码玄学:ORA-01031 与跨平台 ASM 环境下的密文同步刺客

💣 踩坑场景: 所有主备参数都对,网也没问题,但 MRP 始终起不来或者切换时目标库死活不接受命令,后台疯狂报 ORA-01031: insufficient privileges 或者抛出各种 Authentication failed(认证失败)。 🔍 核心原因: 密码文件(Password File)里的 SYS 密码 Hash 校验不通过!这在主备两边操作系统版本不同(比如主库红帽7,备库红帽8)或者两边跑在 ASM 环境下时,堪称隐藏极深的巨坑。 在 11g 时代,密码文件还是放在文件系统里的文本;但是到了 12c 及 19c 的 Grid 架构里,为了给 RAC 或 ADG 加持,很多兄弟把密码文件(orapw<sid>)挪到了 ASM 磁盘组里。由于操作系统底层的 libclntsh 等 SSL 验签算法或者 Grid 底层的认证机制存在些许差异,即便你手工拷过来的密码文件也会因为底层格式引发“水土不服”,导致 Data Guard Broker 或后台心跳日志无法互信。另外,如果主库 DBA 某天随手改了 SYS 密码,没有把新生成的密码文件同步考给备库,也会引发此灾难。

🚑 救命指南: 只要遇到 ORA-01031 权限报错,别去扯什么参数了,一定是密码对不上。干脆利落地“覆写”它。

传统文件系统: 直接从主库机器的 $ORACLE_HOME/dbs/(Linux)目录下将最新的 orapw<sid> 通过 scp 强行覆盖拷贝至备库的同目录下。

ASM 环境的高压线玩法: 因为密码文件埋在 ASM 磁盘组里,你没法直接 scp。这个时候必须用 asmcmd 桥接取出:

# 1. 在主库机器,将 ASM 里的密码文件拉回本地
asmcmd pwcopy +DATA/PROD/PASSWORD/pwdprod.256.123456 /tmp/orapwprod

# 2. 把出来的文件推给备库
scp /tmp/orapwprod oracle@standby_ip:/tmp/

# 3. 在备库机器上,用 asmcmd 将这个新文件狠狠灌进 ASM 替换老文件!
asmcmd pwcopy --dbuniquename PRODSTB /tmp/orapwprod +DATA/PRODSTB/PASSWORD/

盖完之后,两边重新互信认证,MRP 会瞬间接管干活!


四、悬念降临:切换失败死死“卡在两边”,终极拯救闭环

兄弟们,咱们聊一个让所有 DBA 胆寒的极限场景:你果敢地按了命令,原主库非常听话降级成了 Standby,结果新备库那边出了各种幺蛾子死死决裂了,直接 ORA- 死个痛快拒绝提升自身权限。 这下懵逼了。你整个体系里,现在两边都是 Physical Standby(两个干读不写的备库)! 全网业务开始 502⁄504 报错倒计时……你身后,大领导抱着肩膀叹气。

别慌,不要冷汗,一切尽在控制。还记得咱们第二部分里的第五条心法:建立保证还原点(GRP)吗? 你的底牌在这里。既然新主库起不来,那咱就利用闪回立刻把角色反转回去,让岁月重返一切安好的1小时前!

背水一战,重回过去(GRP闪回操作模板)

第一招:先稳住原主库(现在它已经是挂载状态的备库了),让它通过 Flashback 时光倒流。

# 1. 斩断原主库的所有纠缠进程
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;

# 2. 时光倒流至你提前留好的降落伞!
FLASHBACK DATABASE TO RESTORE POINT PRE_SWITCHOVER;

# 3. 这里的动作关键!因为时光倒流到切换前了,它理当是一名主库。强制认主归宗!
ALTER DATABASE CONVERT TO PRIMARY;

# 4. 暴力开库!一定要加上 RESETLOGS 切割时空
ALTER DATABASE OPEN RESETLOGS;

这一套组合拳打下来,原先陷入僵死的首节点立刻满血复活充当 Primary 角色。业务端配置的 SCAN IP 或者 VIP 探测发现库拉起来,业务立马恢复通行,前后不到 3 分钟。

第二招:原先的灾备库怎么处理?也要闪回保持同频,绝对不能丢!

# 原备库侧既然也没切成功,为了防止 SCN 出现脑裂,咱们也给它重回原点!
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
FLASHBACK DATABASE TO RESTORE POINT PRE_SWITCHOVER;

# 然后正常重新挂到MRP状态跑起日志,自动接手主库新产生的 incarnation 和 redo
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT;

打完收工。擦掉额头的汗喝口水。别人问怎么了?微微一笑,说刚才切换碰上了版本底层 Bug 引起主干分叉,安全起见我做了时空倒转毫秒级恢复,数据一致性已经完美保全。妥妥的!


五、幽灵杀手:主备库 Patch 补丁不一致带来的定时炸弹

有很多兄弟喜欢把 Data Guard 备库当成自己的“试验田”,为了不影响主库,偷偷给备库打个 OJVM 或者 RU 补丁测试;甚至在做大版本系统迁移时,找了两台底层操作系统和补丁版本(如 19.3 与 19.17)不一致的机器硬上高可用。这种两边“貌合神离”的架构就是一枚极其致命的定时炸弹!

💣 踩坑场景: 平时主备同步一切完美,一到灾备切换:Database altered. 提示切换命令执行成功。但当你准备带着新主库业务横刀立马时,在 alert 日志和 DBA_REGISTRY 字典树里发现大量核心组件显示为 INVALID 或者 OPTION MISMATCH!随即抛出形态怪异的 ORA-00600 或者 ORA-07445 Coredump 闪退报错,数据库瞬间宕机。

🔍 核心原因: Data Guard 传的是什么?是 Redo 物理日志!它是极其底层的物理块变化(Block Change)。如果你的主库常年不打补丁,运行着某些老旧的结构块,而备库新打的 RU(Release Update)修复了底层的字典表结构。正常接收日志时两者是相安无事的(因为只做块恢复);但只要真正发生 Switchover 或者 Failover,新提升的主库就会用它高级版本的 Oracle 二进制文件(Binary)去强行启动包含了老旧字典块的数据文件——就相当于拿波音 747 的发动机强行套拖拉机的底盘,对象底层指针错乱立刻报底层 ORA-00600 崩溃!

🚨 防御与修复心法:

  1. 统一意志:主库和备库的 $ORACLE_HOME 下的补丁基线和单机 One-Off Patch 必须一模一样! 这是不可撼动的红线!每次演练前通过 opatch lsinventory 进行一次 diff 比对。
  2. 滚动升级需严谨: 如果你确实在跑 Rolling Upgrade(瞬态逻辑备库法打补丁),请务必在一个计划的极短割接窗口内把主库的补丁也全部拉平,不要让这种“长短脚”差异运行过夜。
  3. 补救办法: 如果真因为 Patch 等级不一样导致切库报废(比如打不开,提示跑 datapatch 失败),立刻上第二部分讲的 GRP 时光倒转回到切换前的备库状态!停掉备库,用 opatch rollback 将多出的补丁狠狠卸掉,恢复全平台镜像对齐,然后再发起切换动作!

六、干货总结

兄弟们,老总经常问:Data Guard 原理这么简单不就是传日志吗?为什么一到切的时候就跟做法事一样?

咱们今天盘的这些:ORA-16416,ORA-16475,11g 的死锁 Bug,19c 的 Broker 瞎子陷阱,TNS 幽灵中断……表面上看是不同的报错现象,底层逻辑其实都指向了一个原则:Oracle 对事务严密性和完整性的绝对容不得沙。 哪怕多了一个未决分布式长会话、哪怕网络中间少了一次应答确认,Oracle 宁可自我封停也绝不冒乱丢数据的风险。

作为资深 DBA 架构师,容灾切换考验的从来不是手速敲得多快。而是:

  1. 你对业务停止界限的把控 —— 提前排尽杂念,杀掉残留会话是保障切库的先决条件。
  2. 你应对突发报错的模型框架 —— 遇见报错不慌,脑海里要有底层的状态机走势路图。
  3. 永远不把自己逼入绝境 —— 只要保留了原备份、建立好 GRP,天大的乱子我们也能兜得住。

希望能用我的这篇文章,不仅给大家带来直接可以“抄作业”的代码模板,更能分享那些在冰冷 Linux 控制台后隐藏的心流。下一次深夜操作,老哥祝你指尖下的每一次回车,反馈的都是稳如老狗的 Database altered!

[延伸阅读:更多真实演练与 Failover 极限反杀案例] 光看不够过瘾?对于灾备演练和更暴力的故障转移(Failover)等极端场景,建议老铁们可以“抄一抄”笔者之前实打实跑过的这几场经典战役,保证原汁原味:

真实的实战永远比单纯的文档指令来得刺激,这套“组合拳”看透彻了,以后生产随便切,心里门儿清!咱们下期不见不散!


相关参考文献:

赞(0) 打赏
未经允许不得转载:徐万新之路 » Oracle Data Guard 11g到19c切换避坑指南

支持快讯、专题、百度收录推送、人机验证、多级分类筛选器,适用于垂直站点、科技博客、个人站,扁平化设计、简洁白色、超多功能配置、会员中心、直达链接、文章图片弹窗、自动缩略图等...

联系我们

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

登录

找回密码

注册