适用场景:Oracle Data Guard 三节点级联架构(A 主库 → B 一级备库 → C 二级备库)
数据库版本:Oracle 11gR2+
架构类型:异地级联物理备库(Physical Standby Cascade)
本文档性质:灾备切换演练标准操作手册(SOP)
一、架构说明
1.1 级联灾备架构
┌─────────────────┐
│ 主库 A (PRIMARY) │
│ 数据库: ecms │
│ db_unique_name: ECMS │
└────────┬────────────┘
│ 同步传输(sync)
│ log_archive_dest_2
▼
┌─────────────────┐
│ 一级备库 B (STANDBY)│
│ db_unique_name: ECMSDG1│
└────────┬────────────┘
│ 异步传输(async)
│ log_archive_dest_3
▼
┌─────────────────┐
│ 二级备库 C (STANDBY)│
│ db_unique_name: ECMSDG2│
└─────────────────┘
1.2 初始参数配置参考
| 节点 | db_unique_name | log_archive_dest_2 | fal_server | fal_client |
|---|---|---|---|---|
| A(主库) | ECMS | service=ecmsdg1 async valid_for=(online_logfiles,primary_role) |
— | ECMSDG1 |
| B(一级备) | ECMSDG1 | service=ecms sync valid_for=(all_logfiles,primary_roles) |
ECMS | ECMSDG1 |
| C(二级备) | ECMSDG2 | service=ecmsdg1 async valid_for=(online_logfiles,primary_role) |
ECMSDG1 | ECMSDG2 |
二、切换前检查清单
⚠️ RAC 环境注意:无论主库还是备库,切换前仅保留一个节点,切换后正常启动其余节点即可。
2.1 前提条件检查
| 编号 | 检查项 | 验证方法 | 异常处理 |
|---|---|---|---|
| 0.1 | 主备库 tempfile 文件一致 | SELECT FILE_NAME FROM DBA_TEMP_FILES; |
文件不一致禁止切换 |
| 0.2 | 主备库 redo log 文件一致 | SELECT MEMBER FROM V$LOGFILE; |
补建缺失成员 |
| 0.3 | 归档参数设置正确 | SHOW PARAMETER DEST |
检查日志传输状态 |
| 0.4 | TNS 配置指向正确 | 检查 tnsnames.ora | 重配后重启监听 |
| 0.5 | 操作系统时区和时间一致 | DATE 命令 |
统一时区后重试 |
2.2 切换前状态验证
⚠️ 确保所有节点同步正常,无延迟方可执行切换!
三、当前架构状态检查(A→B→C)
💡 执行任何切换操作前,必须先完成本章节所有检查项。
3.1 检查主库 A 状态
-- 在主库 A 执行
SELECT DATABASE_ROLE, OPEN_MODE, SWITCHOVER_STATUS, PROTECTION_MODE FROM V$DATABASE;
SELECT PROCESS, STATUS, THREAD#, SEQUENCE#, BLOCK#, BLOCKS FROM V$MANAGED_STANDBY;
SELECT MAX(SEQUENCE#) FROM V$ARCHIVED_LOG WHERE APPLIED='YES';
预期结果:
| 检查项 | 预期值 |
|---|---|
DATABASE_ROLE |
PRIMARY |
OPEN_MODE |
READ WRITE |
SWITCHOVER_STATUS |
TO STANDBY 或 SESSION ACTIVE |
3.2 检查备库 B 状态
-- 在备库 B 执行
SELECT DATABASE_ROLE, OPEN_MODE, SWITCHOVER_STATUS FROM V$DATABASE;
SELECT PROCESS, STATUS, THREAD#, SEQUENCE#, BLOCK#, BLOCKS FROM V$MANAGED_STANDBY;
SELECT MAX(SEQUENCE#) FROM V$ARCHIVED_LOG WHERE APPLIED='YES';
预期结果:
| 检查项 | 预期值 |
|---|---|
DATABASE_ROLE |
PHYSICAL STANDBY |
OPEN_MODE |
READ ONLY |
3.3 检查备库 C 状态
-- 在备库 C 执行
SELECT DATABASE_ROLE, OPEN_MODE, SWITCHOVER_STATUS FROM V$DATABASE;
SELECT PROCESS, STATUS, THREAD#, SEQUENCE#, BLOCK#, BLOCKS FROM V$MANAGED_STANDBY;
SELECT MAX(SEQUENCE#) FROM V$ARCHIVED_LOG WHERE APPLIED='YES';
预期结果:
| 检查项 | 预期值 |
|---|---|
DATABASE_ROLE |
PHYSICAL STANDBY |
OPEN_MODE |
READ ONLY |
⚠️ 同步验证:三节点日志序列号差值应 ≤ 1000,否则需先完成日志同步再继续。
四、演练流程
⚠️ 本章节为演练操作流程,演练前需在虚拟机层面打快照,确保可回滚。生产环境执行前请参考第六节。
4.1 切断 A→B 链路并防护反向传输
-- ========== 1.1 登录 A 库,切断 A→B 日志传输 ==========
-- 假设 A 库指向 B 库的通道是 LOG_ARCHIVE_DEST_2
ALTER SYSTEM SET LOG_ARCHIVE_DEST_STATE_2 = DEFER;
-- 验证:确认通道已禁用
SELECT DEST_NAME, STATUS FROM V$ARCHIVE_DEST WHERE DEST_NAME = 'LOG_ARCHIVE_DEST_2';
-- 预期:DEST_STATE = DEFERRED
-- ========== 1.2 登录 B 库,禁用指向 A 库的日志通道 ==========
-- 第一步:查询所有备库通道,定位指向 A 库的通道
SELECT DEST_NAME, DESTINATION FROM V$ARCHIVE_DEST WHERE DESTINATION IS NOT NULL;
-- 第二步:禁用指向 A 库的通道(示例:LOG_ARCHIVE_DEST_3)
ALTER SYSTEM SET LOG_ARCHIVE_DEST_STATE_3 = DEFER;
-- 第三步:禁用 DG Broker(若使用,避免自动反向同步)
ALTER SYSTEM SET DG_BROKER_START = FALSE;
-- 验证
SELECT VALUE FROM V$PARAMETER WHERE NAME = 'dg_broker_start';
-- 预期:FALSE
4.2 在 C 库创建保障还原点
⚠️ 快照优先原则:先对 C 库所在虚拟机打快照,再执行闪回点创建。
-- ========== 2.1 登录 C 库,停止备库恢复进程 ==========
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
-- 验证:恢复进程已停止(无 MRP0 进程)
SELECT PROCESS, STATUS FROM V$MANAGED_STANDBY WHERE PROCESS = 'MRP0';
-- 无结果即成功
-- 配置闪回恢复区(若未配置)
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST_SIZE = 100G;
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST = '/data/flashback';
-- ========== 2.2 创建保障还原点 ==========
CREATE RESTORE POINT c_switchover_before GUARANTEE FLASHBACK DATABASE;
-- 验证:还原点创建成功
SELECT NAME, SCN, TIME, GUARANTEE_FLASHBACK_DATABASE
FROM V$RESTORE_POINT
WHERE NAME = UPPER('c_switchover_before');
-- 预期:GUARANTEE_FLASHBACK_DATABASE = YES
4.3 在 B 库创建保障还原点
-- ========== 3.1 登录 B 库,停止备库恢复进程 ==========
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
-- 验证
SELECT PROCESS, STATUS FROM V$MANAGED_STANDBY WHERE PROCESS = 'MRP0';
-- 配置闪回恢复区
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST_SIZE = 100G;
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST = '/data/flashback';
-- ========== 3.2 创建保障还原点 ==========
CREATE RESTORE POINT b_switchover_before GUARANTEE FLASHBACK DATABASE;
-- 验证
SELECT NAME, SCN, TIME, GUARANTEE_FLASHBACK_DATABASE
FROM V$RESTORE_POINT
WHERE NAME = UPPER('b_switchover_before');
-- 预期:GUARANTEE_FLASHBACK_DATABASE = YES
4.4 重启 C 库恢复进程
-- ========== 4.1 登录 C 库,重启恢复进程 ==========
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT FROM SESSION;
-- 验证:MRP0 进程状态为 RUNNING
SELECT PROCESS, STATUS FROM V$MANAGED_STANDBY WHERE PROCESS = 'MRP0';
4.5 执行 B 库切换为主库
-- ========== 5.1 登录 B 库,执行主备切换 ==========
-- 第一步:验证切换可行性
ALTER DATABASE SWITCHOVER TO PRIMARY VERIFY;
💡 常见报错:
ORA-16468: error connecting to switchover target,通常由网络连接问题导致,可忽略继续执行。
-- 第二步:执行强制切换
ALTER DATABASE ACTIVATE STANDBY DATABASE;
-- 第三步:打开 B 库
ALTER DATABASE OPEN;
-- 验证
SELECT DATABASE_ROLE, OPEN_MODE FROM V$DATABASE;
-- 预期:PRIMARY / READ WRITE
4.5.1 BC 不同步时的补救步骤
⚠️ 如果 B→C 同步断开,需按以下步骤修复:
-- 2.1 在 B 库查询当前化身的第一个归档日志
SELECT NAME, SEQUENCE#, RESETLOGS_CHANGE#
FROM V$ARCHIVED_LOG
WHERE RESETLOGS_CHANGE# = (
SELECT RESETLOGS_CHANGE# FROM V$DATABASE_INCARNATION WHERE STATUS = 'CURRENT'
)
ORDER BY SEQUENCE# ASC;
-- 2.2 在 C 库注册该日志(替换为实际路径)
ALTER DATABASE REGISTER PHYSICAL LOGFILE '/oradata/arch/1_1_1227453307.dbf';
# 2.3 重置 C 库的化身(在 RMAN 中执行)
# C 库需处于 MOUNT 状态
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
-- RMAN 中执行
RESET DATABASE TO INCARNATION 2;
-- 3.1 查询 resetlogs_change# 并执行恢复
SELECT RESETLOGS_CHANGE#, RESETLOGS_TIME
FROM V$DATABASE_INCARNATION WHERE STATUS = 'CURRENT';
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE UNTIL CHANGE <RESETLOGS_CHANGE#>;
-- 3.2 重启实时恢复进程
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT FROM SESSION;
4.6 B→C 链路演练(含 BC 互切)
4.6.1 验证 B→C 正常同步
-- 登录 B 库,检查日志传输状态
SET LINESIZE 200;
COL DESTINATION FOR A40;
SELECT DEST_ID, DESTINATION, STATUS, ERROR, FAIL_DATE FROM V$ARCHIVE_DEST;
-- 登录 C 库,检查同步 SCN(与 B 库差值 ≤ 1000 为正常)
-- B 库:查询当前 SCN
SELECT CURRENT_SCN FROM V$DATABASE;
-- B 库:创建同步测试表
CREATE TABLE BC_SWITCHOVER_TEST AS SELECT SYSTIMESTAMP AS TIMES FROM DUAL;
-- C 库:查询恢复 SCN
SELECT RECOVERY_CURRENT_SCN FROM V$DATABASE;
-- C 库:验证同步
SELECT * FROM BC_SWITCHOVER_TEST;
4.6.2 执行 B→C 主备切换(C 升格为主库)
-- 6.2.1 登录 B 库,切换为备库
ALTER DATABASE COMMIT TO SWITCHOVER TO PHYSICAL STANDBY WITH SESSION SHUTDOWN;
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
-- 6.2.2 登录 C 库,切换为主库
ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY WITH SESSION SHUTDOWN;
ALTER DATABASE OPEN;
-- 6.2.3 登录 B 库,启动备库恢复进程
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT FROM SESSION;
-- 验证切换结果
-- B 库:
SELECT DATABASE_ROLE FROM V$DATABASE;
-- 预期:PHYSICAL STANDBY
-- C 库:
SELECT DATABASE_ROLE FROM V$DATABASE;
-- 预期:PRIMARY
4.6.3 验证 C 作为主库的业务可用性
-- 登录 C 库,创建测试表并写入数据
CREATE TABLE TEST_BC_SWITCH (
ID NUMBER PRIMARY KEY,
CONTENT VARCHAR2(100),
CREATE_TIME DATE DEFAULT SYSDATE
);
INSERT INTO TEST_BC_SWITCH (ID, CONTENT) VALUES (1, 'C作为主库写入测试');
INSERT INTO TEST_BC_SWITCH (ID, CONTENT) VALUES (2, 'BC互切演练数据');
COMMIT;
-- 登录 B 库,验证同步
SELECT * FROM TEST_BC_SWITCH;
-- 预期:查到 2 条测试数据
4.6.4 执行 C→B 主备切回(B 恢复为主库)
-- 6.4.1 登录 C 库,切换为备库
ALTER DATABASE COMMIT TO SWITCHOVER TO PHYSICAL STANDBY WITH SESSION SHUTDOWN;
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
-- 6.4.2 登录 B 库,切换回主库
ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY WITH SESSION SHUTDOWN;
ALTER DATABASE OPEN;
-- 6.4.3 登录 C 库,启动备库恢复进程
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT FROM SESSION;
-- 验证切回结果
-- B 库:
SELECT DATABASE_ROLE FROM V$DATABASE;
-- 预期:PRIMARY
-- C 库:
SELECT DATABASE_ROLE FROM V$DATABASE;
-- 预期:PHYSICAL STANDBY,MRP0 进程 RUNNING
4.6.5 验证 B→C 同步恢复正常
-- 登录 B 库,插入测试数据验证同步
INSERT INTO TEST_BC_SWITCH (ID, CONTENT) VALUES (3, '切回后B主库写入');
COMMIT;
-- 登录 C 库,验证同步
SELECT * FROM TEST_BC_SWITCH WHERE ID = 3;
-- 预期:查到该数据
4.7 恢复 A→B→C 原始架构(Flashback 回滚)
⚠️ 演练完成后,通过保障还原点回滚所有变更,恢复原始架构。
步骤 0:回滚前置准备
-- 1. 清理演练测试数据(在 B/C 库执行)
DROP TABLE TEST_BC_SWITCH PURGE;
DROP TABLE BC_SWITCHOVER_TEST PURGE;
-- 2. 阻断 B→C 的临时日志传输
-- 登录 B 库
ALTER SYSTEM SET LOG_ARCHIVE_DEST_STATE_2 = DEFER;
-- 登录 C 库
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
步骤 1:闪回 B 库(核心优先)
-- 登录 B 库执行
-- 1.1 关闭 B 库(演练后 B 是主库状态)
SHUTDOWN IMMEDIATE;
-- 1.2 启动到 MOUNT 状态
STARTUP MOUNT;
-- 1.3 闪回到演练前还原点
FLASHBACK DATABASE TO RESTORE POINT b_switchover_before;
-- 验证
SELECT NAME, SCN FROM V$RESTORE_POINT WHERE NAME = UPPER('b_switchover_before');
SELECT CURRENT_SCN FROM V$DATABASE;
-- 应与还原点 SCN 一致
-- 1.4 将 B 库切回物理备库角色
ALTER DATABASE COMMIT TO SWITCHOVER TO PHYSICAL STANDBY;
-- 验证
SELECT DATABASE_ROLE FROM V$DATABASE;
-- 预期:PHYSICAL STANDBY
-- 1.5 启动备库恢复进程
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT FROM SESSION;
-- 验证
SELECT PROCESS, STATUS FROM V$MANAGED_STANDBY WHERE PROCESS = 'MRP0';
-- 预期:RUNNING
步骤 2:闪回 C 库
-- 登录 C 库执行
-- 2.1 关闭 C 库
SHUTDOWN IMMEDIATE;
-- 2.2 启动到 MOUNT 状态
STARTUP MOUNT;
-- 2.3 闪回到演练前还原点
FLASHBACK DATABASE TO RESTORE POINT c_switchover_before;
-- 验证
SELECT NAME, SCN FROM V$RESTORE_POINT WHERE NAME = UPPER('c_switchover_before');
SELECT CURRENT_SCN FROM V$DATABASE;
-- 应与还原点 SCN 一致
-- 2.4 重启 C 库恢复进程
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT FROM SESSION;
-- 验证
SELECT PROCESS, STATUS FROM V$MANAGED_STANDBY WHERE PROCESS = 'MRP0';
-- 预期:RUNNING
步骤 3:恢复 B→C 日志传输
-- 登录 B 库
ALTER SYSTEM SET LOG_ARCHIVE_DEST_STATE_2 = ENABLE;
-- 验证
SELECT DEST_NAME, STATUS, DEST_STATE
FROM V$ARCHIVE_DEST WHERE DEST_NAME = 'LOG_ARCHIVE_DEST_2';
-- 预期:DEST_STATE = ENABLE,STATUS = VALID
步骤 4:恢复 A→B 日志传输
-- 登录 A 库
ALTER SYSTEM SET LOG_ARCHIVE_DEST_STATE_2 = ENABLE;
-- 验证
SELECT DEST_NAME, STATUS, DEST_STATE
FROM V$ARCHIVE_DEST WHERE DEST_NAME = 'LOG_ARCHIVE_DEST_2';
-- 预期:DEST_STATE = ENABLE,STATUS = VALID
五、身份重置(如需重建备库)
⚠️ 备库切换后如遇化身不一致问题,执行以下重置。
-- 查看当前化身记录
SET LINESIZE 200 PAGESIZE 200
SELECT * FROM V$DATABASE_INCARNATION;
-- MOUNT 状态下重置化身
ALTER DATABASE RESET DATABASE TO INCARNATION 2;
六、生产切换注意事项
⚠️ 生产环境执行灾备切换前,务必满足以下条件:
| 序号 | 注意事项 |
|---|---|
| 1 | 提前通知业务方,获取切换窗口 |
| 2 | 确认备库日志应用无延迟(SCN 差值 ≤ 1000) |
| 3 | 所有还原点必须在虚拟机快照之后创建 |
| 4 | 演练中删除的测试表需确认已清理 |
| 5 | 回滚后需重新验证主备数据一致性 |
| 6 | 切换完成后更新监控告警配置(主库 IP 变更) |
七、演练 vs 生产对比
| 维度 | 演练环境 | 生产环境 |
|---|---|---|
| 快照保护 | ✅ 必需,演练前打 VM 快照 | N/A |
| 保障还原点 | ✅ 必需,GUARANTEE FLASHBACK | ✅ 必需(生产前创建) |
| 业务通知 | 可选 | 必需,提前沟通切换窗口 |
| 回滚窗口 | 充裕,可多次尝试 | 严格受限于业务窗口 |
| 验证完整性 | 全部验证项 | 核心验证项优先 |
本文档基于 Oracle Data Guard 级联灾备架构整理,适用于 Oracle 11gR2 及以上版本。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




