Skip to main content

Oracle Data Guard Failover to Standby

Oracle Data Guard failover to standby database

Introduction

Failover occurs when the primary database is completely lost or becomes inaccessible. In such events, the standby database is promoted to serve as the new primary to ensure service continuity. The original primary does not automatically transition to a standby role, particularly if it is damaged or unrecoverable. If Flashback Database is not enabled on the original primary, it becomes necessary to re-create the primary database from scratch, using a method such as RMAN Duplicate.

Prerequisites

  • Oracle Data Guard should already be configured between the primary and standby.
  • This guide assumes the primary database is completely lost.

Environment Used in This Guide

Server Primary Standby
Hostname Source Target
IP 192.168.80.51 192.168.80.111
OS OEL 9 OEL 9
SID ORCLDC ORCLDR
Service Name ORCLDC ORCLDR

Please note that failover (activating the standby) is destructive and should only be used when the primary is completely lost. Use these steps as appropriate for your own environment, and never run this against production purely for testing.

Step 1: Check the Standby Database Status

Before doing anything destructive, confirm the standby is in a healthy state and check how far behind it is from the primary's last known sequence. A small or zero apply gap gives confidence that failing over won't lose much data.


SQL> select NAME, DB_UNIQUE_NAME, DATABASE_ROLE, OPEN_MODE, LOG_MODE from v$database;

NAME      DB_UNIQUE_NAME                 DATABASE_ROLE    OPEN_MODE       LOG_MODE
--------- ------------------------------ ---------------- --------------- ------------
ORCL      ORCLDR                         PHYSICAL STANDBY MOUNTED         ARCHIVELOG

SQL> select process,status,thread#,sequence#,block# from v$managed_standby where process like '%MRP%';

PROCESS   STATUS          THREAD#  SEQUENCE#     BLOCK#
--------- ------------ ---------- ---------- ----------
MRP0      APPLYING_LOG          1        284        868

SQL>
SQL> set lines 200 pages 300
SQL> alter session set nls_date_format= 'DD-MON-YYYY HH24:MI:SS';
Session altered.
SQL> select d.db_unique_name,d.database_role, a.thread#, b.last_seq, a.applied_seq, b.last_seq - a.applied_seq ARC_DIFF, a.last_app_timestamp,
round((sysdate - a.last_app_timestamp)*24*60,2) Gap_in_Mins, round((sysdate - a.last_app_timestamp)*24*60*60,2) Gap_in_Seconds
FROM
(select thread#, MAX(sequence#) applied_seq, MAX(next_time) last_app_timestamp from gv$archived_log where REGISTRAR='RFS' and applied='YES' group by thread#) a,
(select thread#, MAX(sequence#) last_seq from gv$archived_log group by thread#) b,
(select db_unique_name,database_role from v$database) d where a.thread#=b.thread#;  

DB_UNIQUE_NAME                 DATABASE_ROLE       THREAD#   LAST_SEQ APPLIED_SEQ   ARC_DIFF LAST_APP_TIMESTAMP   GAP_IN_MINS GAP_IN_SECONDS
------------------------------ ---------------- ---------- ---------- ----------- ---------- -------------------- ----------- --------------
ORCLDR                         PHYSICAL STANDBY          1        283         283          0 04-MAY-2025 21:29:47     2335.62         140137

Step 2: Cancel and Finish Managed Recovery on the Standby

Stop redo apply and let the standby finish applying anything already in progress before activating it. Activating a standby while managed recovery is still running can leave the database in an inconsistent state.


SQL> alter database recover managed standby database cancel;

Database altered.

SQL> alter database recover managed standby database finish;

Database altered.

SQL>

Step 3: Activate the Standby

This is the step that actually promotes the standby to the primary role. Once activated, there's no automatic path back, so this should only be done when the original primary is confirmed lost.


SQL> select NAME, DB_UNIQUE_NAME, DATABASE_ROLE, OPEN_MODE, LOG_MODE from v$database;

NAME      DB_UNIQUE_NAME                 DATABASE_ROLE    OPEN_MODE       LOG_MODE
--------- ------------------------------ ---------------- --------------- ------------
ORCL      ORCLDR                         PHYSICAL STANDBY MOUNTED         ARCHIVELOG

SQL> alter database activate standby database;

Database altered.

SQL> select NAME, DB_UNIQUE_NAME, DATABASE_ROLE, OPEN_MODE, LOG_MODE from v$database;

NAME      DB_UNIQUE_NAME                 DATABASE_ROLE    OPEN_MODE       LOG_MODE
--------- ------------------------------ ---------------- --------------- ------------
ORCL      ORCLDR                         PRIMARY          MOUNTED         ARCHIVELOG

SQL>

Step 4: Bounce the Database

A fresh restart brings the newly promoted primary fully online in READ WRITE mode, ready to serve normal application traffic.


SQL> select NAME, DB_UNIQUE_NAME, DATABASE_ROLE, OPEN_MODE, LOG_MODE from v$database;

NAME      DB_UNIQUE_NAME                 DATABASE_ROLE    OPEN_MODE       LOG_MODE
--------- ------------------------------ ---------------- --------------- ------------
ORCL      ORCLDR                         PRIMARY          MOUNTED         ARCHIVELOG

SQL>
SQL> shut immediate;
ORA-01109: database not open

Database dismounted.
ORACLE instance shut down.
SQL>
SQL> startup
ORACLE instance started.

Total System Global Area 1459616616 bytes
Fixed Size                  9177960 bytes
Variable Size            1224736768 bytes
Database Buffers          218103808 bytes
Redo Buffers                7598080 bytes
Database mounted.
Database opened.
SQL>
SQL> select NAME, DB_UNIQUE_NAME, DATABASE_ROLE, OPEN_MODE, LOG_MODE from v$database;

NAME      DB_UNIQUE_NAME                 DATABASE_ROLE    OPEN_MODE       LOG_MODE
--------- ------------------------------ ---------------- --------------- ------------
ORCL      ORCLDR                         PRIMARY          READ WRITE      ARCHIVELOG

SQL>

Step 5: Take a Full Database Backup

With the new primary open and serving traffic, take an immediate full backup. There's no standby protecting this database anymore, so this backup is your only safety net until a new standby is built.


run
{
allocate channel ch1 device type disk;
backup as compressed backupset database format '/u01/app/oracle/rmanbkp/Fullback_%T_%U';
backup as compressed backupset archivelog all format '/u01/app/oracle/rmanbkp/Archive_%T_%U';
backup current controlfile format '/u01/app/oracle/rmanbkp/Controlback_%T_%U';
release channel ch1;
}

The former standby is now running as the primary, fully open, and backed up. If the original primary is ever recovered, it can no longer resume as primary without being rebuilt from scratch and re-instantiated as a new standby, using a method such as RMAN Duplicate.

Thank you for reading!

I hope this content has been helpful to you. Your feedback and suggestions are always welcome. Feel free to leave a comment or reach out with any queries.

Abhishek Shrivastava

Oracle DBA with hands-on experience managing production Data Guard, RAC, GoldenGate, and APEX environments. I write practical, tested installation and troubleshooting guides based on real deployment work.

📧 Email: oraeasyy@gmail.com
🌐 Website: www.oraeasy.com

Follow Us

Comments