这篇文章总结Oracle 18c/19c Physical Standby DG的主备切换的操作流程,主要参考官方文档18c & 19c Physical Standby Switchover Best Practices using SQL*Plus (Doc ID 2485237.1)[1].
由于参考官方的最佳实践,所以有些步骤/过程略显繁琐。其实正常情况下,这里面的很多步骤都可以略过。但是不妨我们从更严谨的态度和细节方面了解更多的技术细节。 注意:没有记录表示正常,如果有相关记录返回,则表示数据库存在坏块。 获取主备库的信息以及保护模式(主备库执行) 检查主库下SWITCHOVER_STATUS字段,如果值为"SESSION ACTIVE"或者"TO STANDBY", 则主数据库角色可以切换为备库角色。关于SWITCHOVER_STATUS字段的各个取值如下所示: 检查主库重做日志传输和应用状态 主库(Primary) 重点关注ERROR字段的输出信息,如果重做日志传输和应用有问题,就会有相关错误信息提示。 检查主库最后生成的归档日志文件 主库(Primary) 备库(Standby)检查验证最后收到主库的归档日志 备库(standby)检查最后应用的归档日志序列 --主库(primary)&备库(standby)检查 --检查验证参数 注意事项:要确保兼容参数compatible和noncdb_compatible在主备上一致。 Ensure Prerequisites are completely verified. Along with Prerequisites, Follow the below guidance to have successful switchover.
These steps should be executed before real planned outage starts and ensure no issues. 备库(standby) 这个步骤不是必须的,如果你确认DG最近没有相关数据文件和临时表空间的相关文件调整,可以直接跳过这一步。 --Check the datafiles & Tempfiles status 检查temp表空间的文件 执行下面SQL检查redo log和standby redo log的信息(主库和备库) --检查REDO LOG或归档日志应用延迟。(主库执行) DEST_ID的值可以根据实际情况调整。STATUS字段应该为VALID,GAP_STATUS字段应该为"NO GAP" 主库(Primary)和备库(Standby) 关于检查的具体内容,官方文档描述为 ADG切换验证:(主库执行): 上面命令成功执行的话,则会返回"Database altered.",才可以执行下面命令,否则需要检查分析原因。 上面命令执行成功,主库告警日志中会出现下面信息: 备库的告警日志中也会出现下面日志 如果执行报错,也会在告警日志中看到详细的错误信息。 --Step 1: (主库执行) --Step 2: 旧备库上/新的主库(new primary)执行 --Step 3: 新的备库/旧主库上执行(current/new standby ) --注意:退出之前的sqlplus命令窗口,重新登陆执行命令,否则可能会遇到一些错误。如下例子所示: 将PDB启动到OPEN状态 --Step 4:新的备库开始redo apply --Step 5: 检查确认Switchover是否正常 --主库 --备库(standby) --备库执行SQL,检查同步状态 1: https://support.oracle.com/epmos/faces/DocumentDisplay?_afrLoop=246469404737555&id=2485237.1&_afrWindowMode=0&_adf.ctrl-state=18aegmiut3_4前提条件(Prerequisites)检查
DG的设置/配置验证
$ grep "ORA-" alert_<ORACLE_SID>.log
$ tail -600 alert_<ORACLE_SID>.log | grep "ORA-"
select * from v$database_block_corruption;
select * from v$nonlogged_block;
set linesize 720
col name for a10
col open_mode for a20
col database_role for a16
col switchover_status for a12 heading "SWITCHOVER |STATUS"
col force_logging for a8
col dataguard_broker for a8 heading "DATAGUARD|BROKER"
col guard_status for a8
select name
,open_mode
,database_role
,protection_mode
,protection_level
,switchover_status
,force_logging
,dataguard_broker
,guard_status
from v$database;
SWITCHOVER_STATUS取值
意义
NOT ALLOWED
在主数据库上,此状态表示没有有效且已启用的备用数据库。如果配有DG关系,则表示当前数据库不允许进行Switchover操作。这可能是因为多种原因,如数据库状态不正确、主备库之间存在延迟或不一致、存在活跃的会话等。具体原因需要结合数据库状态和日志信息等来判断。在备用数据库上,此状态表示尚未从主数据库收到切换请求
SESSIONS ACTIVE
表示当前数据库有活跃的会话或事务,这些会话或事务需要被断开或提交后,才能进行Switchover操作。 数据库具有活动会话。在物理备用数据库上,必须指定 WITH SESSION SHUTDOWN 这样的SQL子句才能在此状态下执行角色转换。在逻辑备用数据库上,可以在此状态下执行角色转换,但在提交所有当前事务之前,角色转换不会完成。
SWITCHOVER PENDING
在物理备用数据库上,此状态表示已从主数据库收到切换请求并正在处理。在此瞬态状态下,物理备用数据库无法切换到主要角色。
SWITCHOVER LATENT
在物理备用数据库上,此状态表示切换请求处于挂起状态,但原始主数据库已切换回主要角色。
TO PRIMARY
表示当前数据库可以切换为主数据库(Primary Database)。这通常是在执行Switchover操作后,原备用数据库(Standby Database)切换为主数据库(Primary Database)时显示的状态。
TO STANDBY
表示当前数据库可以切换为备用数据库(Standby Database)。这通常意味着数据库处于可以安全地进行Switchover操作的状态,且没有活跃的会话或事务阻止切换。
TO LOGICAL STANDBY
数据库已从逻辑备用数据库接收到数据字典,并准备切换到逻辑备用角色。
RECOVERY NEEDED
在物理备用数据库上,此状态指示必须先应用额外的重做,然后数据库才能切换到主要角色
PREPARING SWITCHOVER
在主数据库上,此状态表示正在从逻辑备用数据库接收数据字典,以准备切换到逻辑备用角色。在逻辑备用数据库上,此状态表示数据字典已发送到主数据库和其他备用数据库。
PREPARING DICTIONARY
在逻辑备用数据库上,此状态表示正在将数据字典发送到主数据库和其他备用数据库,以准备切换到主要角色。
FAILED DESTINATION
在主数据库上,此状态表示一个或多个备用目标处于错误状态。这个值可能不是SWITCHOVER_STATUS的直接状态值,但在执行Switchover过程中,如果遇到配置错误或网络问题导致目标数据库无法接收归档日志,可能会间接导致Switchover失败,并显示为类似“Failed Destination”的错误信息。这种情况需要DBA检查相关配置和网络连接。
RESOLVABLE GAP
在主数据库上,此状态表示一个或多个备用数据库具有redo gap,可以通过从主数据库或另一个备用数据库获取丢失的重做来自动解决该差距。 在某些情况下,如归档日志传输过程中出现短暂的中断导致日志间隙(Gap),但这些间隙可以通过后续操作解决时,可能会显示为“Resolvable Gap”状态。这通常不是SWITCHOVER_STATUS的直接输出,而是描述问题性质的一种方式。
UNRESOLVABLE GAP
在主数据库上,此状态表示一个或多个备用数据库具有redo缺失(redo gap),无法通过从主数据库或另一个备用数据库获取丢失的redo日志来自动解决该缺口
LOG SWITCH GAP
在主数据库上,此状态表示由于最近的日志切换,一个或多个备用数据库缺失了redo log。
COL DEST_NAME FOR A20
COL DESTINATION FOR A25
COL ERROR FOR A15
COL ALTERNATE FOR A20
SET LINES 1000
SELECT DEST_NAME,DESTINATION,ERROR
,ALTERNATE,TYPE,STATUS
,VALID_TYPE,VALID_ROLE
FROM V$ARCHIVE_DEST
WHERE STATUS <>'INACTIVE';SELECT THREAD#, MAX(SEQUENCE#) "Last Primary Seq Generated"
FROM GV$ARCHIVED_LOG VAL, GV$DATABASE VDB
WHERE VAL.RESETLOGS_CHANGE# = VDB.RESETLOGS_CHANGE#
GROUP BY THREAD# ORDER BY 1;--Using the below query, check the last received archivelog from primary database
--(RAC database result will be displayed for each thread).
SELECT THREAD#, MAX(SEQUENCE#) "Last Standby Seq Received"
FROM GV$ARCHIVED_LOG VAL, GV$DATABASE VDB
WHERE VAL.RESETLOGS_CHANGE# = VDB.RESETLOGS_CHANGE#
GROUP BY THREAD# ORDER BY 1;--Check last archive log sequence applied at standby.
SELECT THREAD#, MAX(SEQUENCE#) "Last Standby Seq Applied"
FROM GV$ARCHIVED_LOG VAL, GV$DATABASE VDB
WHERE VAL.RESETLOGS_CHANGE# = VDB.RESETLOGS_CHANGE#
AND VAL.APPLIED IN ('YES','IN-MEMORY')
GROUP BY THREAD# ORDER BY 1; 验证初始化参数
show parameter log_archive_config;
show parameter fal_server;
show parameter fal_client;
show parameter db_unique_name;
show parameter log_archive_dest_;
show parameter compatible;
show parameter db_file_name_convert;
show parameter log_file_name_convert;
show parameter pdb_file_name_convert;
或
set linesize 720 pagesize 60
col name for a30
col value for a120
SELECT
NAME,
VALUE
FROM
V$PARAMETER
WHERE
NAME IN (
'db_unique_name',
'log_archive_config',
'log_archive_dest_1',
'log_archive_dest_2',
'log_archive_dest_state_1',
'log_archive_dest_state_2',
'remote_login_passwordfile',
'log_archive_format',
'standby_file_management',
'compatible',
'fal_server',
'db_file_name_convert',
'log_file_name_convert'
)
order by name; 切换前工作(Pre-Switchover)
检查MRP进程状态
select * from gv$dataguard_process;
停止/启动MRP进程,特殊情况下执行,此处不用执行。
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT;检查数据文件和Tempfiles
SELECT NAME FROM V$DATAFILE WHERE STATUS='OFFLINE';
--ALTER DATABASE DATAFILE 'datafile-name' ONLINE;set linesize 680
set pagesize 40
col filename for a80
col tablespace for a16
select tf.name filename
, bytes
, ts.name tablespace
from v$tempfile tf, v$tablespace ts where tf.ts#=ts.ts#;检查redo log和standby redo log的信息
set lines 680
col member for a50
select a.thread#,a.group#,a.bytes,a.blocksize,b.type,a.status,b.member
from v$log a,v$logfile b
where a.group#=b.group#
order by a.group#;set lines 680
col member for a50
select s.thread#,s.group#,s.status,s.bytes,l.type,l.member
from v$logfile l,v$standby_log s where s.group#=l.group#
order by s.thread#,s.group#;SELECT STATUS, GAP_STATUS FROM V$ARCHIVE_DEST_STATUS WHERE DEST_ID = 2;
检查监控告警日志
$ tail -600 alert_<ORACLE_SID>.ora | grep ORA
$ tail -60f alert_<ORACLE_SID>.ora1) From primary database alert logfile:
* Check for issue reported for redo transport
* Ensure there is no password file issue
* Ensure there are no TNS or connection issue
2) From Standby database alert logfile:
* There are no error related to Managed recovery
* Recovery is moving forward by applying the archive log / redo log
* There are no TNS or connection issue
* There are no I/O issue or corruption issue
select * from v$database_block_corruption; -- it should return no rows
select * from v$nonlogged_block; -- it should return no rowsDG切换(Switchover)
验证切换(Verify the switchover)
ALTER DATABASE SWITCHOVER TO gspro VERIFY;
2024-07-10T09:11:45.281610+08:00
ALTER DATABASE SWITCHOVER TO gspro VERIFY
2024-07-10T09:11:45.530174+08:00
SWITCHOVER VERIFY: Send VERIFY request to switchover target GSPRO
SWITCHOVER VERIFY COMPLETE: READY FOR SWITCHOVER
Completed: ALTER DATABASE SWITCHOVER TO gspro VERIFY2024-07-10T09:11:45.598106+08:00
SWITCHOVER VERIFY BEGIN
SWITCHOVER VERIFY COMPLETE切换(Switchover)步骤
ALTER DATABASE SWITCHOVER TO gspro;
ALTER DATABASE OPEN;
--If standby is Oracle Active data guard physical standby:
STARTUP;
--If standby is NOT Oracle Active data guard physical standby:
STARTUP MOUNT;SQL> STARTUP;
ORA-32004: obsolete or deprecated parameter(s) specified for RDBMS instance
ORA-49100: Failed to process event statement [10235 trace name context forever,level 2: 7445 trace name heapdump level 2: 10027 trace name context forever,level 1: 10949 trace name context forever,level 1]
ORA-00972: identifier is too longSHOW PDBS;
ALTER PLUGGABLE DATABASE ALL OPEN;ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
alter system archive log current;
set linesize 720;
select dest_id,error,status from v$archive_dest where dest_id=<your remote log_archive_dest_<n>>; --一般为2
select max(sequence#),thread# from v$log_history group by thread#;
select max(sequence#) from v$archived_log where applied='YES' and dest_id=2;select max(sequence#),thread# from v$archived_log group by thread#;
select name,role,instance,thread#,sequence#,action from gv$dataguard_process;set linesize 720;
col name for a24;
col source_db_unique_name for a16;
col value for a16;
col unit for a20;
col time_computed for a19;
col datum_time for a19;
select source_db_unique_name
, name
, value
, unit
, time_computed
, datum_time
from v$dataguard_stats;
SQL> set linesize 720;
SQL> col name for a24;
SQL> col source_db_unique_name for a16;
SQL> col value for a16;
SQL> col unit for a20;
SQL> col time_computed for a19;
SQL> col datum_time for a19;
SQL> select source_db_unique_name
2 , name
3 , value
4 , unit
5 , time_computed
6 , datum_time
7 from v$dataguard_stats;
SOURCE_DB_UNIQUE NAME VALUE UNIT TIME_COMPUTED DATUM_TIME
---------------- ------------------------ ---------------- -------------------- ------------------- -------------------
gspro transport lag +00 00:00:00 day(2) to second(0) 07/10/2024 09:44:36 07/10/2024 09:44:35
interval
gspro apply lag +00 00:00:00 day(2) to second(0) 07/10/2024 09:44:36 07/10/2024 09:44:35
interval
gspro apply finish time +00 00:00:00.000 day(2) to second(3) 07/10/2024 09:44:36
interval
estimated startup time 16 second 07/10/2024 09:44:36
SQL>