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 办法。

相关推荐
冒泡的肥皂3 小时前
MVCC初学demo(一
数据库·后端·mysql
.Shu.4 小时前
Redis Reactor 模型详解【基本架构、事件循环机制、结合源码详细追踪读写请求从客户端连接到命令执行的完整流程】
数据库·redis·架构
薛晓刚6 小时前
当MySQL的int不够用了
数据库
SelectDB技术团队7 小时前
Apache Doris 在菜鸟的大规模湖仓业务场景落地实践
数据库·数据仓库·数据分析·apache doris·菜鸟技术
星空下的曙光7 小时前
mysql 命令语法操作篇 数据库约束有哪些 怎么使用
数据库·mysql
小楓12017 小时前
MySQL數據庫開發教學(一) 基本架構
数据库·后端·mysql
染落林间色7 小时前
达梦数据库-实时主备集群部署详解(附图文)手工搭建一主一备数据守护集群DW
数据库·sql
颜颜yan_8 小时前
企业级时序数据库选型指南:从传统架构向智能时序数据管理的转型之路
数据库·架构·时序数据库
lichenyang4538 小时前
管理项目服务器连接数据库
数据库·后端
沙振宇8 小时前
【数据库】通过‌phpMyAdmin‌管理Mysql数据
数据库·mysql