How to Solve Gaps in Oracle Data Guard Apply

   In most companies that have Oracle database running you will have a standby database that is used for HA or for reports or any other reasons. Some times your standby database will lag behind and will get out of sync with primary database.

gap The error message that will be raised in your standby alert log will look something like this:
Waiting for all non-current ORLs to be archived...
Media Recovery Waiting for thread 1 sequence 1200
Fetching gap sequence in thread 1, gap sequence 1200-1200
FAL[client]: Failed to request gap sequence
For what ever reason the sequence# 1200 was not applied, so none of the logs received later were applied. These means that our Standby database was left behind(out of sync).

Why this might happen ?

Well to get a better view of the problem that caused the standby to fall behind is to check the Primary database alert log. Sometimes the log are deleted, or there is no more space on the disk or the FRA is full.

How to fix this ?

  • 1 - Well you can recreate the standby database but this might take some effort and resources depending on your database size, network performance, database use, etc..
  • 2 - Another option is to apply an incremental backup of Primary starting with the SCN registered in the Standby.
We are going to go for the second option since our database is very large and standby reconstruction will take to much time.

Let's go now and see how we can do this Step by Step

  • 1 - On Standby find the SCN value

sql:SELECT to_char(CURRENT_SCN) FROM V$DATABASE;
50353294709
  • 2 - Stop the MRP process in your Standby database and shutdown the database.

MRP - Managed recovery process - For Data Guard, the background process that applies archived redo log to the standby database.
sql:ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
...
sql: shu immediate;
  • 3 - Connect to the primary database as the RMAN target and create an incremental backup from the current SCN of the standby database that was recorded in step 1

BACKUP INCREMENTAL FROM SCN 50353294709 DATABASE FORMAT '/tmp/STB_INC_%U' tag 'FOR STB';
  • 4 - On the Primary, create a new standby controlfile

alter database create standby controlfile as '/tmp/ctl_stb.ctl';
  • 5 - Copy all of the backup-sets and the controlfile to the host where the Standby database is located.

host@primary: scp /tmp/ctl_stb.ctl STB_INC_* oracle@stb_host:/u01/backup/
  • 6 - Replace the standby control file with the newly generated controlfile form step 4

  • 6.1 - find the location of the actual controlfile

SQL show parameter control

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------

control_files                        string      /u02/oradata/Standby/control
                                                 01.ctl, /u02/oradata/Standby
                                                 /control02.ctl
  • 6.2 - Replace the controlfile with the new one(make sure your database will be shutdown while doing this)

cp /u01/backup/ctl_stb.ctl /u02/oradata/Standby/control01.ctl
cp /u01/backup/ctl_stb.ctl /u02/oradata/Standby/control02.ctl
  • 7 - Start your standby database in mount mode

SQL alter database mount standby database;

Database altered.
  • 8 - Now will recover the Standby database using the incremental backup of primary taken at step 3

On the Standby server, catalog the backupset of the incremental backup taken at step 3.
$ rman nocatalog target /
RMANcatalog start with '/u01/backup/';
....
....
....
-- issue the RECOVER command after the backupsets are cataloged

RMANRECOVER DATABASE NOREDO;
  • 9 - After the recover is done and no errors comeup we will start the Standby Managerd Recovery process

SQL alter database recover managed standby database disconnect from session;
Note: Depending on your Primary & Standby datafile location configuration you might need to rename your datafiles. For this you can use the script bellow to rename the datafile. Make sure the replication process is stopped and your database is in mount mode.
select 'ALTER DATABASE RENAME FILE  '''||name||''' to ''/NEW_STANDBY_LOCATION'|| substr(name,instr(name,'/',-1))||''';' as remane_tmp from v$datafile;
I hope this was helpful. Fell free leave your comments or new posts requests.