当前位置:首页 > 问答 > 正文

ORA-19970报错怎么破,备库切换卡住了远程帮忙解决方案

ORA-19970这个错误代码,通常伴随着类似“备库切换操作因活动会话而卡住”这样的描述,就是你打算把备库切换成主库用,但Oracle发现备库上还有用户正在连接和操作,它担心直接切换会导致数据不一致或这些用户的操作中断出问题,所以它就卡在那里,报了这个错,不让你继续。

这个问题不算特别复杂,但处理起来需要小心,因为是在操作数据库的主备切换,事关数据安全,核心思路就是:清理掉那些妨碍切换的“障碍物”——也就是备库上的所有本地会话。

下面是非常直接、一步步的解决方案,你跟着做就行。(重要提醒:在执行任何操作前,请确保你已经对当前环境做了必要的备份,或者至少已经在测试环境验证过,生产环境操作务必谨慎。)

第一步:立刻检查切换被卡住的具体状态

你先别急着去杀会话,首先得确认是不是真的是这个原因,以及切换进行到哪一步了,用有权限的用户(比如SYS用户)登录到备库上,执行这个查询:

SELECT SWITCHOVER_STATUS FROM V$DATABASE;

你看看返回的结果是什么,如果看到的是 “SESSION ACTIVE”,那就百分之百确认了,就是有活动会话在捣乱,有时候也可能是“TO STANDBY”或者其他状态,但“SESSION ACTIVE”是最常见的原因。

第二步:尝试最文明、最安全的清理方法——发出切换警告

ORA-19970报错怎么破,备库切换卡住了远程帮忙解决方案

Oracle其实提供了一个很文明的功能,它允许你提前通知所有连接到备库的用户:“喂,数据库要维护了,你们赶紧自己断开连接!” 这个命令会在所有会话的数据库端弹出一个消息(如果客户端工具支持的话)。

在备库上执行: ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY WITH SESSION SHUTDOWN;

注意,这里用的是 WITH SESSION SHUTDOWN,而不是更粗暴的方式,这个命令会做两件事:

  1. 尝试通知所有会话。
  2. 给这些会话一个非常短暂的宽限期(比如几秒到几十秒),让它们自己完成当前操作并断开,如果宽限期过后还有会话没断,Oracle才会强制中断它们。

你执行完这个命令后,就等一下,系统会自动处理,很多时候,这样就能成功完成切换了,你可以在执行后再次查询SELECT SWITCHOVER_STATUS FROM V$DATABASE;,看看是不是变成了“TO PRIMARY”或者“SWITCHOVER PENDING”之类的,表示正在切换中或即将完成。

第三步:如果文明方法不行,那就手动定位并清除顽固会话

如果上一步的命令执行后,等了好几分钟还是卡住,或者直接报错说无法完成,说明有一些“顽固”的会话没有被自动清理掉,这时候就需要你手动出手了。

ORA-19970报错怎么破,备库切换卡住了远程帮忙解决方案

  1. 找出所有非核心的活动会话: 在备库上执行以下SQL,这会列出所有目前活动的、非Oracle后台进程的用户会话。 SELECT SID, SERIAL#, USERNAME, PROGRAM, MACHINE, STATUS FROM V$SESSION WHERE TYPE = 'USER' AND STATUS = 'ACTIVE';

    你仔细看这个查询结果:

    • SIDSERIAL#:这是唯一标识一个会话的两个关键ID,待会儿杀会话就要用它们。
    • USERNAME:是哪个用户连上来的。
    • PROGRAMMACHINE:是从什么程序(比如sqlplus.exe、TOAD等)和哪台机器连过来的,这能帮你判断这个会话是干嘛的,是不是真的可以杀,比如你看到一个是你同事用开发工具连上来查数据的,那杀掉就没啥大问题,但如果看到一个可能是某个应用服务器连上来的重要服务,那就要特别小心。
  2. 谨慎地终止会话: 对于查询结果中那些你确认可以中断的会话,使用以下命令逐个杀掉: ALTER SYSTEM DISCONNECT SESSION 'SID,SERIAL#' IMMEDIATE; 把上面的SIDSERIAL#替换成你查到的实际数字,比如查到一个会话SID是123,SERIAL#是4567,那么命令就是: ALTER SYSTEM DISCONNECT SESSION '123,4567' IMMEDIATE;

    为什么用DISCONNECT而不是KILL SESSION 在Data Guard环境下,DISCONNECT ... IMMEDIATE通常是更受推荐的方式,它会更直接地终止会话并回滚其当前事务。

    操作建议: 建议你一个一个杀,每杀一个,就回头再去执行一下第一步的切换命令(ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY;),看看能不能成功,有时候可能就一两个会话是罪魁祸首,清除掉就行了,没必要杀光所有。

第四步:万不得已时的终极方法

ORA-19970报错怎么破,备库切换卡住了远程帮忙解决方案

如果上面手动杀会话的方法还是不行,或者活动会话太多太杂,你无法准确判断,又或者情况紧急必须立刻完成切换,可以考虑这个更强力的方法。

在备库上执行: ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY WITH SESSION SHUTDOWN WAIT;

这个WAIT参数会让命令一直等待,直到所有妨碍切换的会话都被清除(无论是自动还是手动)后,它才会完成,这相当于把清理工作和切换操作绑定在了一起,你可能需要在一个不会断开的会话里(比如用SQL*Plus的/ as sysdba本地连接)执行这个命令,然后另开一个窗口去杀会话。

切换完成后的收尾工作

当你看到切换命令成功执行,并且SELECT SWITCHOVER_STATUS FROM V$DATABASE;返回的结果是“TO PRIMARY”或类似的成功状态后,非常重要的一步是:立即重启备库(现在它已经是新的主库了)!

SHUTDOWN IMMEDIATE; STARTUP;

重启是为了让数据库以全新的主库模式加载,清理掉所有切换前的状态,确保数据库完全正常。

解决ORA-19970的步骤就是:查状态 -> 尝试自动清理 -> 手动精准清除 -> 强力清除 -> 重启新主库。 整个过程的核心就是确保备库在切换时是一个“干净”的状态,没有其他读写操作干扰,希望这些直接的步骤能帮你解决问题。

(本解决方案综合参考了Oracle官方文档关于Data Guard Switchover的说明、Oracle Support社区的知识库文章以及多位DBA在技术论坛上的实战经验分享。)