如何在Oracle DG切换期间处理主库未提交的长事务?

作者:袖梨 2026-07-10
主库未提交的长事务会直接阻断DG Switchover,导致alter database commit to switchover卡住或报ORA-16139、SWITCHOVER_STATUS=SESSIONS ACTIVE等错误;必须通过v$session与v$transaction关联查询识别活跃长事务,结合v$locked_object确认锁持有情况,并区分“真长事务”(需kill session回滚)与“伪长事务”(应联系开发处理),严禁使用GoldenGate命令;Switchover验证失败时需检查归档传输状态、手动切日志并确认MRP已追平Redo,因End of Redo标记仅在所有事务决断后生成。

主库未提交的长事务会直接阻断 dg switchover 流程,alter database commit to switchover 会卡住或报 ora-16139: media recovery requiredswitchover_status = sessions active 等错误。必须先清理或确认这些事务状态,才能继续切换。

查主库是否有未提交的长事务

不能只看 v$transactionstart_time,要结合会话活跃度和锁持有情况:

  • 执行 SELECT s.sid, s.serial#, s.username, s.status, t.start_time, t.used_ublk FROM v$session s, v$transaction t WHERE s.taddr = t.addr ORDER BY t.start_time; —— 找出运行超 10 分钟且 status = 'ACTIVE' 的事务
  • 再关联 v$locked_object:如果该会话正持有行锁或 DML 锁(lock_type = 'TX'),基本可判定是未提交事务在阻塞切换
  • 注意:v$transaction 中的 start_time 是事务开始时间,不是 SQL 执行时间;有些应用开启事务后长期空闲(比如等待前端上传),也会被误判为“长事务”,需人工确认业务逻辑

Switchover 前必须处理的两类事务

一类是“真长事务”(如批量导入中途挂起),另一类是“伪长事务”(连接池中空闲但事务未关闭)。处理方式完全不同:

  • 对已确认业务可中断的真长事务:用 alter system kill session 'sid,serial#' immediate; 强制终止,Oracle 会自动回滚其变更(依赖 UNDO 空间充足)
  • 对伪长事务(常见于 Java 应用未调用 connection.commit()rollback()):优先联系开发,确认是否能主动提交/回滚;若无法联系,再 kill session —— 否则可能引发应用层重试风暴
  • 严禁在主库上执行 send extract ,forcetransskiptrans(这是 GoldenGate 场景,不适用于 DG 切换)

Switchover 验证阶段卡住怎么办

执行 alter database switchover to physical standby verify; 后返回 ORA-16139,说明 MRP 进程还没收完主库发来的最后一批 Redo,或主库仍有未刷盘的 Redo 缓存:

  • 检查主库 v$archive_dest_statusdest_id=2status 是否为 VALIDerror 字段是否为空
  • 在主库手动触发日志切换:ALTER SYSTEM ARCHIVE LOG CURRENT;,重复 2–3 次,确保所有 Redo 已传到备库
  • 在备库查 SELECT MAX(sequence#) FROM v$archived_log WHERE applied='YES';SELECT MAX(sequence#) FROM v$log_history;,两者差值应 ≤ 1;若差距大,说明 MRP 还没追平,不能强切

最易被忽略的是:DG 切换不是纯数据库操作,它依赖主库发出的 End of Redo 标记。这个标记只有在主库所有当前事务都提交或回滚后才会生成。任何未决事务都会让这个标记发不出去——所以别跳过事务排查,直接硬切。

相关文章

精彩推荐