Oracle 11g Data Guard 环境中的 GAP 处理办法

概述

在Data Guard 环境中,当主库的某些日志没有成功传送到备库时,就会发生归档裂缝(Archive Gap)。目前,Oracle 提供了两种日志 GAP 的检测和处理机制:自动 GAP 处理(Automatic Gap Resolution)和 FAL 进程 GAP 处理(FAL Gap Resolution)。

  • 自动 GAP 处理:主库上的 ARCn 进程会每分钟检查备库上的日志 GAP 情况并做相应处理。
  • FAL 进程 GAP 处理:通过配置 FAL_SERVER 和 FAL_CLIENT 实现 GAP 检测的一种机制,备库主动发起"取"日志的过程。FAL 进程只在物理备库存在,该进程只有在需要的时候才会启动,工作完成后关闭。

大致可以分为以下几种情况来处理:

  1. 主库归档日志存在:可以通过配置 Fetch Archive Log (FAL) 参数,自动解决归档 GAP,或将归档日志拷贝到从库手工注册处理。
  2. 主库归档日志丢失 :需要人工干预来修复,11G具体步骤如下:
    1. 以备库的当前 SCN 号为起点,在主库上做一个增量备份。
    2. 在主库上创建一个备库的控制文件。
    3. 将增量备份拷贝到备库上。
    4. 使用新的控制文件将备库启动到 mount 状态。
    5. 将增量备份注册到 RMAN 的 catalog,取消备库的恢复应用,恢复增量备份。
    6. 开启备库的恢复进程。
处理 GAP 方法 1:手动拷贝归档到备库进行手工注册处理(归档未丢失)
(一)物理 DG 手动解决 GAP

在一些特殊情况下,如果 GAP 不能自动解决,那么就需要手工执行中断恢复。通过查询视图 V$ARCHIVE_GAP 可以确定断档的是哪些日志。

sql 复制代码
-- 查询 GAP
SQL> SELECT * FROM V$ARCHIVE_GAP;

假设当前物理备库丢失日志文件从线程 1 的序号 10 到序号 12。接下来确定归档日志文件的路径(假设在主数据库上的本地归档目的地是 LOG_ARCHIVE_DEST_1):

sql 复制代码
-- 确定归档日志文件路径
SQL> SELECT NAME FROM V$ARCHIVED_LOG WHERE THREAD#=1 AND DEST_ID=1 AND SEQUENCE# BETWEEN 10 AND 12;

接下来,将这些日志文件拷贝到物理备库,然后在物理备库上使用 ALTER DATABASE REGISTER LOGFILE 语句来注册这些归档日志:

sql 复制代码
-- 注册归档日志
SQL> ALTER DATABASE REGISTER LOGFILE '/arch/thread1_dest/arch_1_10.arc';
-- 或者
SQL> ALTER DATABASE REGISTER OR REPLACE LOGFILE '/arch/thread1_dest/arch_1_10.arc';
SQL> ALTER DATABASE REGISTER OR REPLACE PHYSICAL LOGFILE '/arch/thread1_dest/arch_1_11.arc';

在物理备库上注册这些日志文件之后,重新打开重做应用进程。如果断档的归档日志较多,可以使用以下 SQL 语句来生成要执行的 SQL 语句(也适用于逻辑 DG):

sql 复制代码
SELECT 'ALTER DATABASE REGISTER OR REPLACE LOGICAL LOGFILE ''/arch/thread1_dest/arch_1_' || a || '.arc'';' LOGICAL_DG,
       'ALTER DATABASE REGISTER OR REPLACE LOGFILE ''/arch/thread1_dest/arch_1_' || a || '.arc'';' PHYSICAL_DG
FROM (SELECT LEVEL A FROM DUAL CONNECT BY LEVEL <= 12)
WHERE A >= 10;
(二)逻辑 DG 手动解决 GAP

在逻辑备库上查询 DBA_LOGSTDBY_LOG 视图可以确定是否有归档中断。例如,下面的查询指出断档号为 16 至 18:

sql 复制代码
-- 查询断档日志
SQL> COLUMN FILE_NAME FORMAT a60
SQL> SELECT THREAD#, SEQUENCE#, FILE_NAME
  2  FROM DBA_LOGSTDBY_LOG L
  3  WHERE NEXT_CHANGE# NOT IN (SELECT FIRST_CHANGE# FROM DBA_LOGSTDBY_LOG WHERE L.THREAD# = THREAD#)
  4  ORDER BY THREAD#, SEQUENCE#;

接下来将丢失的日志文件拷贝到逻辑备库,并在逻辑备库上使用 ALTER DATABASE REGISTER LOGICAL LOGFILE 来注册这些日志文件。例如:

sql 复制代码
-- 注册日志文件
SQL> ALTER DATABASE REGISTER LOGICAL LOGFILE '/arch/oracle/arch_1_16.arc';

在逻辑备库上注册这些日志文件之后,重启 SQL 应用。和物理 DG 一样,在逻辑备库上的 DBA_LOGSTDBY_LOG 视图只返回当前妨碍 SQL 应用继续的下一个中断。在解决指定的中断并重启 SQL 应用之后,再次在逻辑备库上查询 DBA_LOGSTDBY_LOG 视图,以确定下一个中断序号,重复这个过程直到没有更多的中断。

需要注意的是,如果需要的归档日志已经不在主库上了,但是有归档日志的 RMAN 备份,那么可以通过 RMAN 恢复把缺少的归档日志进行还原,如下所示:

sql 复制代码
-- 设置归档日志目标位置
SET ARCHIVELOG DESTINATION TO '/arch';

-- 恢复归档日志
RESTORE ARCHIVELOG FROM LOGSEQ 17;

处理GAP方法2:主库基于SCN的增量备份来恢复DG(归档丢失)

如果断档的归档日志已经丢失,且RMAN又没有备份,那么在Oracle 10g之前没有办法修复了,只能重建DG,但是从Oracle 10g开始可以采用主库基于SCN的增量备份来恢复DG。

下面我们通过实验来进行展示11g环境中基于SCN的增量备份来恢复DG(常规办法):

示例

首先,模拟备库断电,主库切几个最新的归档,然后手工删掉,重新开启 DG 同步。

备库操作
sql 复制代码
-- 停止备库的 redo apply
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;

-- 关闭备库
SHUTDOWN IMMEDIATE;
主库操作
sql 复制代码
-- 切换多个日志
ALTER SYSTEM SWITCH LOGFILE; -- 多次执行

-- 删除最近几个归档日志
rm 1_30_1070147166.arc
rm 1_31_1070147166.arc
备库操作
sql 复制代码
-- 启动备库
STARTUP

-- 使用当前日志文件恢复
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT FROM SESSION;
查看 GAP
sql 复制代码
-- 查看 GAP
SQL> SELECT * FROM V$ARCHIVE_GAP;

-- 查看已应用的最大序列号
SQL> SELECT MAX(SEQUENCE#) FROM V$ARCHIVED_LOG WHERE APPLIED='YES';

-- 查看备库的状态
SQL> SELECT PROCESS, STATUS, THREAD#, SEQUENCE#, BLOCK#, BLOCKS FROM V$MANAGED_STANDBY;

假设当前 GAP 为 32-34,下面是具体的处理步骤:

  1. 以备库的当前 SCN 号为起点,在主库上做一个增量备份

    • 备库:

      sql 复制代码
      SELECT TO_CHAR(CURRENT_SCN) FROM V$DATABASE;
    • 主库:

      sql 复制代码
      rman target /
      RUN
      {
        ALLOCATE CHANNEL C1 TYPE DISK;
        ALLOCATE CHANNEL C2 TYPE DISK;
        ALLOCATE CHANNEL C3 TYPE DISK;
        ALLOCATE CHANNEL C4 TYPE DISK;
        BACKUP AS COMPRESSED BACKUPSET INCREMENTAL FROM SCN 16010653817 DATABASE FORMAT '/backup/incre_db_%d_%T_%s.bak';
        BACKUP CURRENT CONTROLFILE FOR STANDBY FORMAT '/backup/standby.ctl';
        RELEASE CHANNEL C1;
        RELEASE CHANNEL C2;
        RELEASE CHANNEL C3;
        RELEASE CHANNEL C4;
      }
  2. 在主库上创建一个备库的控制文件(前面备份集已经备份这里可以不用做)

    sql 复制代码
    ALTER DATABASE CREATE STANDBY CONTROLFILE AS '/backup/standby.ctl';
  3. 将增量备份拷贝到备库上

    bash 复制代码
    scp /backup/incre_* oracle@STANDBY:/backup/
    scp /backup/standby.ctl oracle@STANDBY:/backup/
  4. 使用新的控制文件将备库启动到 mount 状态

    sql 复制代码
    SHUTDOWN IMMEDIATE;
    STARTUP NOMOUNT;
    rman target /
    RESTORE CONTROLFILE FROM '/backup/standby.ctl';
    ALTER DATABASE MOUNT;
  5. 增量备份注册到 RMAN 的 catalog,取消日志应用,恢复增量备份

    sql 复制代码
    ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
    rman target /
    CATALOG START WITH '/backup/';
    RECOVER DATABASE NOREDO;
  6. 备库开启日志同步进程

    sql 复制代码
    sqlplus / as sysdba
    ALTER DATABASE OPEN READ ONLY;
    ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT FROM SESSION;

    主库重新激活同步:

    sql 复制代码
    sqlplus / as sysdba
    ALTER SYSTEM SET LOG_ARCHIVE_DEST_STATE_2=defer;
    ALTER SYSTEM SET LOG_ARCHIVE_DEST_STATE_2=enable;

    查询是否存在 GAP,确认主备是否同步:

    sql 复制代码
    sqlplus / as sysdba
    SELECT * FROM V$ARCHIVE_GAP;
    SELECT MAX(sequence#) FROM v$archived_log WHERE applied='YES';

至此,DG GAP 已被修复,以上方式为常规修复方式,各个版本都通用。

总结

到这里,12c版本之前的常规处理GAP 问题应该得到了解决。 后面我们会继续整理从12c开始 使用RECOVER ... FROM SERVICE的方法以及从18c开始 使用RECOVER STANDBY DATABASE FROM SERVICE的方法来处理 GAP 办法。

相关推荐
老王笔记32 分钟前
MySQL如何区分幻读和不可重复读
数据库·mysql
不爱学习的啊Biao33 分钟前
【08】MySQL复杂查询:子查询语句详解与示例
数据库·mysql·子查询
st_3339 分钟前
Junit5 单元测试入门
数据库·单元测试·log4j
s***g54041 分钟前
MySQL-操作数据库备份与恢复
数据库·mysql
CQU_JIAKE1 小时前
11.5【算法】6-1 表彰优秀学生(多态)
数据库
Elastic 中国社区官方博客2 小时前
使用数据层进行数据生命周期管理
大数据·数据库·elasticsearch·搜索引擎·全文检索·时序数据库
我爱李星璇2 小时前
Spring Boot项目的创建
java·数据库·spring boot
锵锵锵锵~蒋2 小时前
实时数据开发|Flink异步IO--提升性能和吞吐量
jvm·数据库·flink·实时数据开发
小麦项目管理指南3 小时前
工程企业需要什么样的财务软件?
大数据·数据库·信息可视化·项目管理
全栈开发帅帅3 小时前
基于springboot+vue实现的创新创业学分管理系统 (源码+L文+ppt)4-111
spring boot·后端·oracle