Skip to main content

How to Perform a Switchover in Logical Standby

Oracle Logical Standby switchover completing with database roles reversed

Introduction

A switchover is a role reversal between the primary database and one of its standby databases. In this article we will see how to perform a switchover activity in a Logical Standby setup.

Prerequisites

  • Logical standby should be configured and in sync.
  • 30 mins downtime at database end.

Environment Used in this Guide

Server Primary Standby
Hostname dcdb.oraeasy.com drdb.oraeasy.com
OS OEL 9 OEL 9
SID ORADBDC ORADBDR
Service Name ORADBDC ORADBDR

Switchover Activity Step by Step

Step 1: Check the Sync Between Primary and Standby

Confirm the logical standby is fully caught up before starting a switchover. Attempting one against a lagging standby risks data loss or an extended outage.


Primary:
SQL> select name,db_unique_name,database_role,open_mode from v$database; NAME DB_UNIQUE_NAME DATABASE_ROLE OPEN_MODE --------- ------------------------------ ---------------- -------------------- ORADB oradbdc PRIMARY READ WRITE SQL> alter system switch logfile; System altered. SQL> / System altered. SQL> select max(sequence#) from v$archived_log; MAX(SEQUENCE#) -------------- 73 Standby:
SQL> select name,db_unique_name,database_role,open_mode from v$database; NAME DB_UNIQUE_NAME DATABASE_ROLE OPEN_MODE --------- ------------------------------ ---------------- -------------------- DRDB oradbdr LOGICAL STANDBY READ WRITE SQL> SELECT NAME, VALUE, UNIT FROM V$DATAGUARD_STATS; NAME VALUE UNIT -------------------------------- ---------------------------------------------------------------- ------------------------------ transport lag +00 00:00:05 day(2) to second(0) interval apply lag +00 00:00:05 day(2) to second(0) interval apply finish time +00 00:00:00.001 day(2) to second(3) interval estimated startup time 26 second SQL> select sequence#,first_change#,next_change#,timestamp,applied,blocks,block_size from dba_logstdby_log; SEQUENCE# FIRST_CHANGE# NEXT_CHANGE# TIMESTAMP APPLIED BLOCKS BLOCK_SIZE ---------- ------------- ------------ --------- -------- ---------- ---------- 48 2359387 2379644 18-DEC-25 YES 141188 512 49 2379644 2410748 18-DEC-25 YES 182159 512 50 2410748 2412399 18-DEC-25 YES 1924 512 51 2412399 2412440 18-DEC-25 YES 118 512 52 2412440 2414499 18-DEC-25 YES 1178 512 53 2414499 2416312 18-DEC-25 YES 1147 512 54 2416312 2416320 18-DEC-25 YES 14 512 55 2416320 2416401 18-DEC-25 YES 52 512 56 2416401 2417392 18-DEC-25 YES 568 512 57 2417392 2419821 18-DEC-25 YES 15093 512 58 2419821 2419827 18-DEC-25 YES 13 512 59 2419827 2422503 18-DEC-25 YES 2086 512 60 2422503 2424463 18-DEC-25 YES 1083 512 61 2424463 2425309 18-DEC-25 YES 474 512 68 2438855 2440179 20-DEC-25 YES 1165 512 62 2425309 2426595 18-DEC-25 YES 703 512 39 2355105 2355125 17-DEC-25 YES 40 512 63 2426595 2429603 18-DEC-25 YES 39291 512 64 2429603 2432435 18-DEC-25 YES 2273 512 65 2432435 2434380 18-DEC-25 YES 1082 512 66 2434380 2436356 18-DEC-25 YES 1116 512 67 2436356 2438855 18-DEC-25 YES 10530 512 38 2354571 2355105 17-DEC-25 YES 38359 512 41 2358171 2358214 17-DEC-25 YES 22 512 42 2358214 2358226 17-DEC-25 YES 20 512 43 2358226 2358460 17-DEC-25 YES 120 512 44 2358460 2358471 17-DEC-25 YES 16 512 45 2358471 2358481 17-DEC-25 YES 16 512 46 2358481 2359121 17-DEC-25 YES 350 512 70 2459307 2462128 20-DEC-25 YES 2515 512 47 2359121 2359387 18-DEC-25 YES 218 512 71 2462128 2464114 20-DEC-25 YES 1246 512 72 2464114 2464739 20-DEC-25 YES 327 512 73 2464739 2464749 20-DEC-25 CURRENT 15 512 40 2355125 2358171 17-DEC-25 YES 2685 512 69 2440179 2459307 20-DEC-25 YES 144626 512 36 rows selected.

Zero transport lag and apply lag, together with the standby's dba_logstdby_log entries all showing APPLIED, confirm it's safe to begin the switchover.

Step 2: Prepare to Switchover on the Primary

The switchover process starts on the primary by signaling its intent to become the new standby.


SQL> select switchover_status from v$database;

SWITCHOVER_STATUS
--------------------
TO STANDBY

SQL> alter database prepare to switchover to logical standby;

Database altered.

SQL> select switchover_status from v$database;

SWITCHOVER_STATUS
--------------------
PREPARING SWITCHOVER

SWITCHOVER_STATUS moving from TO STANDBY to PREPARING SWITCHOVER confirms the primary has begun the handoff and is flushing final redo to the standby.

Step 3: Prepare to Switchover on the Standby

The standby must independently prepare for its new role as primary.


SQL> select switchover_status from v$database;

SWITCHOVER_STATUS
--------------------
NOT ALLOWED

SQL> alter database prepare to switchover to primary;

Database altered.

SQL> select switchover_status from v$database;

SWITCHOVER_STATUS
--------------------
PREPARING SWITCHOVER

SWITCHOVER_STATUS moving to PREPARING SWITCHOVER on the standby confirms both databases are now aligned and ready for the actual role switch.

Step 4: Commit to Switchover on the Primary

Check the switchover status on the primary first, and only run the commit command once it reads TO LOGICAL STANDBY. This is the go/no-go check, since committing before this status appears can fail the switchover.


SQL> select switchover_status from v$database;

SWITCHOVER_STATUS
--------------------
TO LOGICAL STANDBY

SQL> alter database commit to switchover to logical standby;

Database altered.

SQL> select name,db_unique_name,database_role,open_mode from v$database;

NAME      DB_UNIQUE_NAME                 DATABASE_ROLE    OPEN_MODE
--------- ------------------------------ ---------------- --------------------
ORADB     oradbdc                        LOGICAL STANDBY  READ WRITE
                                                 

DATABASE_ROLE now reporting LOGICAL STANDBY confirms the former primary (oradbdc) has completed its role change.

Step 5: Commit to Switchover on the Standby

Check the switchover status on the standby, and only run the commit command once it reads TO PRIMARY.


SQL> select switchover_status from v$database;

SWITCHOVER_STATUS
--------------------
TO PRIMARY

SQL> alter database commit to switchover to primary;

Database altered.

SQL> select name,db_unique_name,database_role,open_mode from v$database;

NAME      DB_UNIQUE_NAME                 DATABASE_ROLE    OPEN_MODE
--------- ------------------------------ ---------------- --------------------
DRDB      oradbdr                        PRIMARY          READ WRITE

DATABASE_ROLE now reporting PRIMARY confirms the former standby (oradbdr) is now the primary database, completing the role reversal.

Step 6: Switch Logs on the New Primary and Check Sync

With roles reversed, confirm the new configuration is replicating correctly. Logical standby apply has to be explicitly restarted on the new standby after a switchover, since it doesn't resume automatically the way physical standby recovery does.


Primary:
SQL> alter system switch logfile; System altered. SQL> / System altered. SQL> select max(sequence#) from v$archived_log; MAX(SEQUENCE#) -------------- 31 Standby:
SQL> alter database start logical standby apply immediate; Database altered. SQL> SELECT NAME, VALUE, UNIT FROM V$DATAGUARD_STATS; NAME VALUE UNIT -------------------------------- ------------------- ------------------------------ transport lag +00 00:00:00 day(2) to second(0) interval apply lag +00 00:00:00 day(2) to second(0) interval apply finish time +00 00:00:00.000 day(2) to second(3) interval estimated startup time 28 second SQL> select sequence#,first_change#,next_change#,timestamp,applied,blocks,block_size from dba_logstdby_log; SEQUENCE# FIRST_CHANGE# NEXT_CHANGE# TIMESTAMP APPLIED BLOCKS BLOCK_SIZE ---------- ------------- ------------ --------- -------- ---------- ---------- 27 2497644 2497970 20-DEC-25 YES 38333 512 28 2497970 2497978 20-DEC-25 YES 7 512 29 2497978 2501570 20-DEC-25 YES 16436 512 30 2501570 2503802 20-DEC-25 YES 10108 512 31 2503802 2503810 20-DEC-25 YES 14 512 SQL>

Zero lag on all V$DATAGUARD_STATS metrics confirms the new standby (the former primary, oradbdc) is fully caught up under its new role.

Step 7: Create a User on the New Primary and Check on the New Standby

Final verification: create a user on the new primary and confirm it replicates to the new standby, proving the switched-over configuration works end to end.


Primary:
SQL> def DEFINE _DATE = "20-DEC-25" (CHAR) DEFINE _CONNECT_IDENTIFIER = "oradbdr" (CHAR) DEFINE _USER = "SYS" (CHAR) DEFINE _PRIVILEGE = "AS SYSDBA" (CHAR) DEFINE _SQLPLUS_RELEASE = "1928000000" (CHAR) DEFINE _EDITOR = "vi" (CHAR) DEFINE _O_VERSION = "Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.28.0.0.0" (CHAR) DEFINE _O_RELEASE = "1928000000" (CHAR) SQL> select username from dba_users where username='TEST2'; no rows selected SQL> create user TEST2 identified by Test##123; User created. SQL> select username from dba_users where username='TEST2'; USERNAME ------------------------------------- TEST2 SQL> alter system switch logfile; System altered. Standby:
SQL> def DEFINE _DATE = "20-DEC-25" (CHAR) DEFINE _CONNECT_IDENTIFIER = "oradbdc" (CHAR) DEFINE _USER = "SYS" (CHAR) DEFINE _PRIVILEGE = "AS SYSDBA" (CHAR) DEFINE _SQLPLUS_RELEASE = "1928000000" (CHAR) DEFINE _EDITOR = "vi" (CHAR) DEFINE _O_VERSION = "Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.28.0.0.0" (CHAR) DEFINE _O_RELEASE = "1928000000" (CHAR) SQL> SQL> select username from dba_users where username='TEST2'; USERNAME ------------------------------ TEST2

The TEST2 user appearing on the new standby (oradbdc) confirms the switchover is complete and replication is functioning correctly in the reversed direction.



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

↑