Oracle 11g DataGuard GAP处理

1 说明

在Oracle Data Guard中,GAP是指在备库无法接收到一个或多个来自主库的归档日志文件时发生的情况,会导致数据保护和实时数据复制的能力受到影响。

Oracle Data Guard架构日志同步有三个阶段:

  1. 日志发送;
  2. 日志接收;
  3. 日志应用。

GAP问题常发生在第一阶段日志发送环节,Primary在运行过程中,会不断产生Redo日志,这些Redo日志需要发送到Standy,这个发送动作由Primary的LGWR或者ARCH进程完成,选择使用什么进程进行日志发送,由log_archive_dest_2参数控制。

2 故障模拟

原理是阻断主库日志发送,然后删除新产生的归档,这样就生成GAP了。log_archive_dest_2参数定义了主库归档日志传输到备用数据库的方式和目标,当此参数不生效时,主库就无法将日志发送至备库。

步骤大致如下:

  1. 阻止日志发送;
  2. 主库切日志;
  3. 主库删除归档;
  4. 恢复日志发送。

2.0 当前状态

查看是否有gap:

sql 复制代码
SQL> select thread#, low_sequence#, high_sequence# from v$archive_gap;

当前不存在gap

查看日志应用状态:

sql 复制代码
set lines 200
col name for a70
alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
select *
  from (select name, sequence#, first_time, next_time, archived, applied
          from v$archived_log
         where name is not null
         order by sequence# desc)
 where rownum <= 20;

最新应用的归档序列号是349。

2.1 阻止日志发送

有多种方式可以阻止主库将日志发送到备库,比如将备库关闭,或设置log_archive_dest_state_2为defer。

这里采用第二中方式,不用麻烦关机。

一、设置log_archive_dest_state_2参数

在主库中将此参数设置为defer,暂停日志的发送到standby。

sql 复制代码
SQL> alter system set log_archive_dest_state_2 = 'defer' scope = both;

System altered.

刷新日志:

查看LNS进程状态:

sql 复制代码
SQL> select process, status, SEQUENCE#, delay_mins, block#, blocks from v$managed_standby where process = 'LNS';

PROCESS   STATUS        SEQUENCE# DELAY_MINS     BLOCK#     BLOCKS
--------- ------------ ---------- ---------- ---------- ----------
LNS       CLOSING             320          0      13560          1

LNS进程已经关闭,此时主库已经停止日志发送。

2.2 主库切日志

主库多切几次日志,生成新的归档。

sql 复制代码
SQL> alter system switch logfile;

System altered.

SQL> /

System altered.

SQL> /

System altered.

SQL> /

System altered.

查看日志发送情况:

sql 复制代码
SQL> select process, status, SEQUENCE#, delay_mins, block#, blocks from v$managed_standby order by SEQUENCE#;

可以看到最新的归档日志是355,但是日志发送停止在了351,还有3个日志未发送。

2.3 创建新数据

创建测试数据,用于恢复后验证。

sql 复制代码
SQL> create tablespace ts_gaptest datafile '+DATA';

Tablespace created.


SQL> select file_name from dba_data_files where tablespace_name = 'TS_GAPTEST';

FILE_NAME
----------------------------------------------------------------------
+DATA/orcl/datafile/ts_gaptest.278.1183716375


SQL> create user us_gaptest identified by us_gaptest default tablespace ts_gaptest;

User created.

SQL> grant dba to us_gaptest;

Grant succeeded.

SQL> create table us_gaptest.tab_gaptest as select * from dba_objects;

Table created.

SQL> select count(*) from us_gaptest.tab_gaptest;

  COUNT(*)
----------
     86358

SQL> alter system switch logfile;

System altered.

新增了数据文件+DATA/orcl/datafile/ts_gaptest.278.1183716375,创建了表us_gaptest.tab_gaptest

2.4 主库删除归档

将新生成的那几个还未发送到standby的归档日志删除掉。首先,找到要删除的归档文件:

sql 复制代码
set lines 200
col name for a70
alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
select *
  from (select name, sequence#, first_time, next_time, archived, applied
          from v$archived_log
         where name is not null
         order by sequence# desc)
 where rownum <= 20;

备库:

主库:

可以看到,主库多了352至357号归档,将这几个文件删除。

bash 复制代码
[oracle@oracle11g ~]$ cd /u01/app/oracle/arch/
[oracle@oracle11g arch]$ rm -rf 1_352_1166397622.dbf 1_353_1166397622.dbf 1_354_1166397622.dbf 1_355_1166397622.dbf 1_356_1166397622.dbf 1_357_1166397622.dbf

RMAN检查已经发现这几个归档无效:

sql 复制代码
RMAN> crosscheck archivelog all;

2.5 恢复日志发送

在主库中将log_archive_dest_state_2参数还原,恢复日志发送。

sql 复制代码
SQL> alter system set log_archive_dest_state_2 = 'enable' scope = both;

切个日志:

sql 复制代码
SQL> alter system switch logfile;

System altered.

2.6 查看GAP

备库告警日志提示出现GAP:

备库查看GAP相关视图:

sql 复制代码
SQL> select thread#, low_sequence#, high_sequence# from v$archive_gap;

上述结果都提示了缺失352到357号归档日志文件。

3 处理过程

3.1 备库查看当前scn

sql 复制代码
SQL> select CURRENT_SCN FROM V$DATABASE;

CURRENT_SCN
-----------
    2687514

此scn为恢复的起点。

3.2 查看新增数据文件

sql 复制代码
SQL> SELECT FILE#, NAME FROM V$DATAFILE WHERE CREATION_CHANGE# > 2687514;

     FILE# NAME
---------- ----------------------------------------------------------------------
         8 +DATA/orcl/datafile/ts_gaptest.278.1183716375

在scn为2687514后有一个新创建的数据文件8,需要进行恢复。

3.3 增量备份缺失数据和控制文件

在主库上,做一个基于scn为2687514的数据库增量备份:

sql 复制代码
RMAN> backup incremental from scn 2687514 database format '/home/oracle/orabak/scn2687514_%d_%T_%U_%s';

创建备库控制文件:

sql 复制代码
SQL> alter database create standby controlfile as '/home/oracle/orabak/controlfile.ctl';

Database altered.

3.4 将备份发送到备库

将刚刚创建的增备和控制文件发送到备库。

bash 复制代码
[oracle@oracle11g orabak]$ scp * oracle11gadg:/home/oracle/orabak/
oracle@oracle11gadg's password:
controlfile.ctl                                                                                                                                 100%   13MB  13.3MB/s   00:00
scn2687514_ORCL_20241030_mk38s8bj_1_1_724                                                                                                       100%   29MB  29.0MB/s   00:00
scn2687514_ORCL_20241030_ml38s8bq_1_1_725                                                                                                       100%   13MB  13.3MB/s   00:0

3.5 备库重启到nomount状态

关闭日志应用:

sql 复制代码
SQL> alter database recover managed standby database cancel;

闭库:

sql 复制代码
SQL> shutdown immediate;

启动至nomount状态:

sql 复制代码
SQL> startup nomount;

3.6 控制文件恢复

使用备份恢复控制文件。

sql 复制代码
RMAN> restore controlfile from '/home/oracle/orabak/controlfile.ctl';

恢复后启动之mount状态:

sql 复制代码
RMAN> alter database mount;

将增量备份集信息导入到当前控制文件:

sql 复制代码
RMAN> catalog start with '/home/oracle/orabak/';

3.7 恢复缺失的数据文件

查看文件8信息:

bash 复制代码
RMAN> report schema;

对比主库发现,主库中Size为100,而备库这里size为0。

执行恢复:

sql 复制代码
RMAN> restore datafile 8;

恢复后再次查看发现size已经为100:

数据文件8恢复完成。

3.8 增备恢复

sql 复制代码
RMAN> recover database noredo;

4 备库开启日志应用

打开备库:

sql 复制代码
SQL> alter database open read only;

开启日志应用:

sql 复制代码
SQL> alter database recover managed standby database using current logfile disconnect;

查看进程状态:

sql 复制代码
SQL> select process, status, SEQUENCE#, delay_mins, block#, blocks from v$managed_standby order by SEQUENCE#;

MRP0进程应用日志正常。

5 恢复后检查

备库查看gap:

sql 复制代码
SQL> select thread#, low_sequence#, high_sequence# from v$archive_gap;

no rows selected

gap已经消失。

查看归档是否一致:

sql 复制代码
SQL> select max(sequence#) from v$archived_log;

MAX(SEQUENCE#)
--------------
           362

主备库都为362。

查看新建的表是否恢复:

sql 复制代码
SQL> select count(*) from us_gaptest.tab_gaptest;

  COUNT(*)
----------
     86358

表已经恢复。

相关推荐
hykDatabases31 分钟前
Oracle内置函数及自定义函数
数据库·oracle
HelloZheQ33 分钟前
数据库故障排查指南
数据库·oracle
lixora33 分钟前
Cluster Interconnect in Oracle RAC
oracle
我科绝伦(Huanhuan Zhou)16 小时前
Oracle免费认证来袭
数据库·oracle
YUNYINGXIA1 天前
MySQL数据库初体验
数据库·oracle
焱焱枫1 天前
Oracle 数据布局探秘:段与区块的内部机制
数据库·oracle
焱焱枫1 天前
深入理解 Oracle 数据块:行迁移与行链接的性能影响
数据库·oracle
杨云龙UP2 天前
SQL 中的中括号 [ ]、双引号 “ “、反引号 ` `:SQL Server、Oracle、MySQL三大数据库标识符 定界符 详解
数据库·sql·mysql·postgresql·oracle·sqlserver
cyhysr2 天前
oracle 触发器与commit的先后执行顺序
数据库·oracle
w23617346012 天前
MySQL的information_schema在SQL注入中的关键作用与防御策略
sql·mysql·oracle·注入