Back to Blog
Oracle 10 min readMay 29, 2025

Oracle Standby Database Rebuild Using RMAN — Control File Restore & Recovery

Step-by-step procedure to rebuild an Oracle physical standby when it falls too far behind primary or after a control file issue — using RMAN to restore the control file from primary, catalog existing ASM datafiles, recover from service, and recreate standby redo logs.

When to Use This Procedure

Rebuild the standby when:

  • Standby has fallen behind primary and archive gap is too large to recover normally
  • Control file is corrupted or out of sync with primary
  • After adding large datafiles on primary that the standby cannot receive via MRP
  • Standby redo log size mismatch causing MRP failures

Step 1 — Check Current SCN & Stop MRP

sql
-- Check current SCN on primary
SELECT current_scn FROM v$database;

-- Check minimum SCN across all datafile headers (on standby)
SELECT MIN(fhscn) FROM x$kcvfh;

-- MRP process status before stopping
SELECT process, status, thread#, sequence#, blocks, block#
FROM v$managed_standby;
sql
-- Stop MRP process
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;

-- Temporarily set file management to MANUAL
ALTER SYSTEM SET standby_file_management=MANUAL SCOPE=BOTH SID='*';

Step 2 — Restore Standby Control File from Primary

Connect via RMAN and restore a fresh control file directly from the primary:

bash
rman target /

RMAN> SHUTDOWN IMMEDIATE;
RMAN> STARTUP NOMOUNT;

RMAN> RUN {
  ALLOCATE CHANNEL t1 TYPE DISK;
  RESTORE STANDBY CONTROLFILE FROM SERVICE sfdcp_DGMGRL;
}

RMAN> ALTER DATABASE MOUNT;
💡

This pulls the current primary control file over the network — no dump file required. Requires the DGMGRL TNS service to be reachable.

Step 3 — Handle FRA Conflicts

If the FRA (Flash Recovery Area) path in the restored control file conflicts with current settings, temporarily clear it:

sql
-- Check current FRA settings
SHOW PARAMETER db_recovery_file_dest;

-- Temporarily clear FRA to avoid path conflicts
ALTER SYSTEM SET db_recovery_file_dest='' SCOPE=BOTH SID='*';
💡

You will restore this setting after recovery is complete.

Step 4 — Catalog Existing Datafiles from ASM

Tell RMAN about datafiles already on the standby ASM diskgroup — avoids copying all data from scratch:

bash
# Run catalog in background (can take time for large databases)
nohup rman target /   cmdfile='/oracle/backup/standby_rebuild/catalog.rcv'   log='/oracle/backup/standby_rebuild/catalog.log' &

# catalog.rcv contents:
CATALOG START WITH '+SFDCP_DATA/SFDCS/DATAFILE/' NOPROMPT;
💡

This registers the existing standby datafiles with the new control file. Without this step, RMAN would try to restore all datafiles from primary — massively increasing recovery time for large databases.

Step 5 — Switch Database to Use Cataloged Copies

sql
-- Switch all datafiles to use the cataloged copies
-- (run this in RMAN after catalog completes)
SWITCH DATABASE TO COPY;

Step 6 — Recover from Primary Service

Recover the standby to catch up with primary using RMAN's recover from service. Use many channels for a large/busy database:

bash
nohup rman target /   cmdfile='/oracle/backup/standby_rebuild/recover.rcv'   log='/oracle/backup/standby_rebuild/recover.log' &

# recover.rcv contents:
RUN {
  ALLOCATE CHANNEL prmy1  TYPE DISK;
  ALLOCATE CHANNEL prmy2  TYPE DISK;
  ALLOCATE CHANNEL prmy3  TYPE DISK;
  ALLOCATE CHANNEL prmy4  TYPE DISK;
  ALLOCATE CHANNEL prmy5  TYPE DISK;
  ALLOCATE CHANNEL prmy6  TYPE DISK;
  ALLOCATE CHANNEL prmy7  TYPE DISK;
  ALLOCATE CHANNEL prmy8  TYPE DISK;
  ALLOCATE CHANNEL prmy9  TYPE DISK;
  ALLOCATE CHANNEL prmy10 TYPE DISK;
  ALLOCATE CHANNEL prmy11 TYPE DISK;
  ALLOCATE CHANNEL prmy12 TYPE DISK;
  ALLOCATE CHANNEL prmy13 TYPE DISK;
  ALLOCATE CHANNEL prmy14 TYPE DISK;
  ALLOCATE CHANNEL prmy15 TYPE DISK;
  ALLOCATE CHANNEL prmy16 TYPE DISK;
  ALLOCATE CHANNEL prmy17 TYPE DISK;
  ALLOCATE CHANNEL prmy18 TYPE DISK;
  ALLOCATE CHANNEL prmy19 TYPE DISK;
  ALLOCATE CHANNEL prmy20 TYPE DISK;
  RECOVER DATABASE FROM SERVICE sfdcp_DGMGRL
    NOREDO
    USING COMPRESSED BACKUPSET;
}
💡

NOREDO means only datafile blocks are transferred — redo is applied later by MRP.USING COMPRESSED BACKUPSET reduces network transfer significantly. Monitor recover.log for progress.

Step 7 — Restore FRA Setting

sql
-- Restore FRA after recovery completes
ALTER SYSTEM SET db_recovery_file_dest='+SFDCP_RECO' SCOPE=BOTH SID='*';

SHOW PARAMETER db_recovery_file_dest;

Step 8 — Drop & Recreate Standby Redo Logs

After rebuilding, standby redo logs may have the wrong size or be on incorrect diskgroups. Drop all and recreate with the correct size (must be ≥ primary redo log size):

sql
-- First stop MRP if still running
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;

-- Check existing SRL groups
SELECT group#, dbid, thread#, sequence#, status FROM v$standby_log;

-- Clear and drop (if DROP alone fails due to active state, clear first)
ALTER DATABASE CLEAR LOGFILE GROUP 19;
ALTER DATABASE DROP STANDBY LOGFILE GROUP 19;
-- Repeat for groups 20-42

-- Verify all removed
SELECT group#, status FROM v$standby_log;
sql
-- Recreate at correct size (2G shown — match your primary redo size or larger)
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 19 SIZE 2G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 20 SIZE 2G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 21 SIZE 2G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 22 SIZE 2G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 2 GROUP 23 SIZE 2G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 2 GROUP 24 SIZE 2G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 2 GROUP 25 SIZE 2G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 2 GROUP 26 SIZE 2G;
-- Continue for threads 3-6 (groups 27-42)

Step 9 — Re-enable File Management & Start MRP

sql
-- Re-enable automatic standby file management
ALTER SYSTEM SET standby_file_management=AUTO SCOPE=BOTH SID='*';

-- Start MRP
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;

Step 10 — Verify Sync

sql
-- MRP process and sequence status
SELECT process, status, thread#, sequence#, blocks, block#
FROM v$managed_standby;

-- Data Guard status messages
SELECT message FROM v$dataguard_status;

-- Check for archive gap
SELECT thread#, low_sequence#, high_sequence# FROM gv$archive_gap;

-- Archive destination errors on Primary
SELECT status, error FROM v$archive_dest WHERE dest_id IN (1,2,3,4);

Bonus — Restore Specific Datafiles Only

When only a few datafiles are missing or corrupt on the standby (not a full rebuild), use incremental backup and restore for just those files:

sql
-- Step A: On Primary — backup the specific datafiles
BACKUP DATAFILE 219, 220, 221
  FORMAT '/oracle/backup/incremental/ForStandby_%U'
  TAG 'FORSTANDBY';
bash
# Step B: Transfer the backup pieces to standby
scp /oracle/backup/incremental/ForStandby_*     oracle@standby-server:/oracle/backup/incremental/
sql
-- Step C: On Standby — catalog the backup pieces
CATALOG START WITH '/oracle/backup/incremental/' NOPROMPT;

-- Step D: Restore and rename to ASM
RUN {
  SET NEWNAME FOR DATAFILE 219 TO '+SFDCP_DATA';
  SET NEWNAME FOR DATAFILE 220 TO '+SFDCP_DATA';
  SET NEWNAME FOR DATAFILE 221 TO '+SFDCP_DATA';
  RESTORE DATAFILE 219, 220, 221;
}

-- Step E: Catalog new ASM location
CATALOG START WITH '+SFDCP_DATA/<db_unique_name>/datafile/';

-- Step F: Switch to use the newly restored files
SWITCH DATABASE TO COPY;
💡

This targeted approach is much faster than a full rebuild when only a few datafiles are affected. Useful for adding new tablespaces that the standby did not receive.

All postsOracle · Standby · RMAN · DataGuard · Rebuild

naresh@gowda:~$ built with Next.js + Tailwind + Framer Motion