Switchover VERIFY卡住本质是备库未真正准备好,需依次检查归档接收、日志应用、角色一致性;MRP0卡在APPLYING_LOG且SEQ#不涨多因fast_start_parallel_rollback导致事务恢复死锁;DGMGRL卡住须查Broker日志及监听状态;切换前还需清理活跃会话、停只读应用、校验Broker配置。
Switchover VERIFY卡住,本质是备库没真正“准备好”
不是命令写错了,也不是网络断了——alter database switchover to <standby> verify</standby> 卡住,说明备库当前状态不满足切换前提。oracle 会严格检查归档接收、日志应用、角色一致性三件事,任一环节有延迟或残留,就直接返回等待,不报错也不推进。
典型现象:命令执行后光标不动、SQL*Plus无响应、v$managed_standby 中 MRP0 状态仍是 APPLYING_LOG,但 SEQ# 长时间不更新;或者 DGMGRL 里 show configuration 显示 ERROR,但 show configuration verbose 又是 SUCCESS——这说明 Broker 元数据和实际实例状态已脱节。
- 先查
v$archive_dest_status,确认STATUS = 'VALID'且ERROR列为空;若有 ORA-16057(目标未注册)或 ORA-16775(潜在数据丢失),得先解决归档传输断点 - 再查
v$dataguard_stats,重点看apply_lag和transport_lag是否真为 0 秒(注意“computed X seconds ago”这个时间戳,若 >60 秒,说明统计已过期,需手动刷新) - 最后查
v$fast_start_transactions,如果存在STATE = 'PENDING'且UNDOBLOCKSDONE 的记录,说明大事务回滚卡住,此时必须先处理并行恢复问题(见下一条)
MRP0卡在“APPLYING_LOG”但SEQ#不涨,大概率是fast_start_parallel_rollback惹的祸
备库日志传过来了,MRP0 进程也跑了,就是死活不往前走——这不是磁盘慢或 CPU 不够,而是 Oracle 自己在事务级恢复上“内卷”失败了。12c 默认开启 fast_start_parallel_rollback=LOW,遇到大事务时反而会拉起一堆 P00x 进程争抢资源,导致 SMON 死锁、v$fast_start_servers 里堆满 IDLE 状态进程,最终拖垮整个应用链。
验证方式很简单:查 v$process,如果看到大量 P000–P009 进程,但 v$px_session 为空;同时 v$fast_start_servers 里有多个 RECOVERING 或长期 IDLE 的条目,基本可以锁定。
- 立刻执行:
ALTER SYSTEM SET fast_start_parallel_rollback = FALSE SCOPE=BOTH;—— 动态生效,不用重启 - 执行后观察几分钟:
v$fast_start_servers应快速清空,MRP0退回到串行模式,SEQ#开始递增 - 切完之后可酌情调回(如设为
LOW),但切换窗口内必须保持FALSE
DGMGRL中switchover卡在“Performing switchover NOW, please wait”
Broker 控制下的切换卡住,比 SQL*Plus 更隐蔽。它不像手工命令那样直接暴露底层阻塞点,而是把所有依赖检查打包进一个原子操作里。一旦某个后台任务(比如 Broker 向备库发心跳、校验控制文件 SCN、等待 End of Redo 标记)超时或失败,就会静默挂起。
关键线索藏在 Broker 日志里:$ORACLE_HOME/dbs/dr1<db_name>.log</db_name> 或 $ORACLE_HOME/dbs/dr2<db_name>.log</db_name>,而不是 alert.log。里面常出现 ORA-16775(潜在数据丢失)、ORA-16664(无法从成员收结果)、ORA-16714(属性值不一致)这类错误,但 DGMGRL 终端只显示“please wait”。
- 先运行
show database verbose <standby_name></standby_name>,重点关注Transport Lag和Apply Lag的“computed”时间,若超过 2 分钟,说明 Broker 已失去对备库状态的实时感知 - 检查备库监听器是否健康:
lsnrctl status要返回正常,且服务名(尤其是 DG 所用的静态注册服务)必须在线;ORA-12547 错误常导致 Broker 心跳失败,此时要调大备库sqlnet.ora中的SQLNET.INBOUND_CONNECT_TIMEOUT - 临时停掉 Broker:
DGMGRL> disable configuration,再手工用 SQL*Plus 在主备库分别执行SWITCHOVER VERIFY和SWITCHOVER TO,能绕过 Broker 的中间校验层,快速定位是配置问题还是实例状态问题
Switchover前最易被忽略的“软性阻塞点”
有些问题不报错、不卡进程,但会让切换在最后一刻失败——比如主库还有活跃会话、备库开了只读查询、甚至只是 Broker 配置里多了一个空格。这些细节不会出现在官方文档的 checklist 里,却在真实生产中高频触发。
- 主库上不能有
ACTIVE状态的用户会话(v$session.status = 'ACTIVE'),哪怕只是个空闲但未提交的事务;建议切换前执行ALTER SYSTEM KILL SESSION '<sid>,<serial>'</serial></sid>清理 - 备库若启用了
READ ONLY WITH APPLY,必须先停应用:ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;,否则SWITCHOVER TO PRIMARY会因“数据库处于只读状态”拒绝执行 - Broker 配置中
LogXptMode必须是ASYNC或SYNC,不能是ARCH;后者表示仅靠 ARCH 进程传日志,不保证实时性,Broker 会直接拒绝切换 - 所有节点(尤其 RAC 环境)的
local_listener和remote_listener必须指向有效的 SCAN 或 VIP,否则 Broker 在跨节点通信时会超时静默失败
真正难处理的,从来不是参数本身,而是那些“看起来一切正常,但就是差一口气”的状态同步缝隙。











