Oracle 19c Physical Standby with Data Guard Broker: Complete Step-by-Step Guide

Physical Standby with Data Guard Broker

RMAN Active Duplicate, standby redo logs, Broker configuration, real-time apply, and manual switchover — a validated implementation pattern.

Table of contents

  1. Objective
  2. Target architecture
  3. Prerequisites & pre-checks
  4. Configure Oracle Net & listener
  5. Create the standby instance
  6. RMAN Active Database Duplicate
  7. Validate the physical standby
  8. Standby redo logs
  9. Configure & enable Broker
  10. Validate transport & apply
  11. Planned switchover test
  12. Troubleshooting
  13. Production checklist
  14. Conclusion

Objective

Build an Oracle Database 19c physical standby using RMAN Active Database Duplicate, then configure Data Guard Broker for a Broker-managed configuration with asynchronous redo transport and real-time apply. Fast-Start Failover (FSFO) is intentionally disabled; role transitions stay manual and operator-controlled.

Naming used throughout this guide: DB_NAME=DATAVERLABS, primary DB_UNIQUE_NAME=VERADBPRD, standby DB_UNIQUE_NAME=VERADBPRD_DR, Broker configuration DATAVERLABS_DG. Hostnames (dataveraproddb.dataveralabs.local / dataveraproddbdr.dataveralabs.local) are documentation placeholders — replace with your actual FQDNs.

Target architecture

Oracle Data Guard
                         ASYNC
        +----------------------------------+
        |                                  |
        v                                  |
PRIMARY                                  STANDBY
VERADBPRD                             VERADBPRD_DR
DB_NAME=DATAVERLABS                        DB_NAME=DATAVERLABS
READ WRITE                              MOUNTED
        |                                  |
        +---------- Redo Transport --------+

Broker Configuration: DATAVERLABS_DG
Protection Mode: MaxPerformance
FSFO: Disabled
Apply Delay: 0 minutes

Prerequisites & pre-checks

Confirm the primary is in ARCHIVELOG mode, is the expected primary, and has FORCE LOGGING enabled before touching anything else.

SELECT NAME, DB_UNIQUE_NAME, DATABASE_ROLE, OPEN_MODE,
       LOG_MODE, FORCE_LOGGING
FROM V$DATABASE;

Expected result DATABASE_ROLE=PRIMARY, OPEN_MODE=READ WRITE, LOG_MODE=ARCHIVELOG, FORCE_LOGGING=YES.

SELECT GROUP#, THREAD#, BYTES/1024/1024 AS SIZE_MB, STATUS
FROM V$LOG
ORDER BY GROUP#;

Expected result Reference design: 5 online redo groups, Thread 1, 10,240 MB each.

Verify ASM has enough free space in +DATA and +REDO for the database copy, online redo, standby redo logs, and headroom for growth:

SELECT NAME, TOTAL_MB, FREE_MB,
       ROUND(FREE_MB/TOTAL_MB*100,2) AS FREE_PCT
FROM V$ASM_DISKGROUP
ORDER BY NAME;

Configure Oracle Net & listener

Configure matching TNS aliases on both servers — replace placeholder hostnames with your real primary and DR hosts.

VERADBPRD =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = dataveraproddb.dataveralabs.local)(PORT = 1610))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = VERADBPRD)
    )
  )

VERADBPRD_DR =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = dataveraproddbdr.dataveralabs.local)(PORT = 1610))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = VERADBPRD_DR)
    )
    (UR = A)
  )

VERADBPRD_DR_DGMGRL =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = dataveraproddbdr.dataveralabs.local)(PORT = 1610))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = VERADBPRD_DR_DGMGRL)
    )
  )
tnsping VERADBPRD
tnsping VERADBPRD_DR
tnsping VERADBPRD_DR_DGMGRL

Expected result All three aliases resolve. TNS-03505 means the alias isn’t visible from the active Oracle Net configuration — see Troubleshooting.

Standby listener configuration:

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)
        (HOST = dataveraproddbdr.dataveralabs.local)
        (PORT = 1610))
    )
  )

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = VERADBPRD_DR)
      (SID_NAME = VERADBPRD_DR)
      (ORACLE_HOME = /u01/app/oracle/product/19.0.0/db_1)
    )
    (SID_DESC =
      (GLOBAL_DBNAME = VERADBPRD_DR_DGMGRL)
      (SID_NAME = VERADBPRD_DR)
      (ORACLE_HOME = /u01/app/oracle/product/19.0.0/db_1)
    )
  )

ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER = ON
VALID_NODE_CHECKING_REGISTRATION_LISTENER = ON

Expected result lsnrctl status LISTENER — the static Broker service may show UNKNOWN before dynamic registration; this is normal for a static SID entry.

Create the standby instance directory structure and a dummy pfile

export ORACLE_BASE=/u01/app/oracle
export ORACLE_SID=VERADBPRD_DR
export ORACLE_HOME=$ORACLE_BASE/product/19.0.0/db_1
export TNS_ADMIN=$ORACLE_HOME/network/admin
export PATH=$ORACLE_HOME/bin:/usr/bin:/bin:$PATH
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib:/usr/local/lib
*.db_name='DATAVERLABS'
*.db_unique_name='VERADBPRD_DR'
*.db_block_size=8192
*.compatible='19.0.0'
*.db_files=5000
*.db_create_file_dest='+DATA'
*.remote_login_passwordfile='EXCLUSIVE'
*.sga_target=77158m
*.pga_aggregate_target=25720m
*.processes=3000
*.sessions=4536
*.open_cursors=800
*.enable_pluggable_database=true
*.undo_tablespace='UNDOTBS1'
*.undo_retention=4500
*.audit_trail='db'
*.diagnostic_dest='/u01/app/oracle'
*.audit_file_dest='/u01/app/oracle/admin/VERADBPRD_DR/adump'
sqlplus / as sysdba
STARTUP NOMOUNT PFILE='/path/to/standby_init.ora';

Expected result: Standby instance starts in NOMOUNT.

RMAN Active Database Duplicate

Connect to the primary as TARGET and the standby as AUXILIARY.

rman target "sys@VERADBPRD" auxiliary "sys@VERADBPRD_DR"

RUN {
  ALLOCATE CHANNEL c1 DEVICE TYPE DISK;
  ALLOCATE CHANNEL c2 DEVICE TYPE DISK;
  ALLOCATE CHANNEL c3 DEVICE TYPE DISK;
  ALLOCATE CHANNEL c4 DEVICE TYPE DISK;

  ALLOCATE AUXILIARY CHANNEL a1 DEVICE TYPE DISK;
  ALLOCATE AUXILIARY CHANNEL a2 DEVICE TYPE DISK;
  ALLOCATE AUXILIARY CHANNEL a3 DEVICE TYPE DISK;
  ALLOCATE AUXILIARY CHANNEL a4 DEVICE TYPE DISK;

  DUPLICATE TARGET DATABASE
    FOR STANDBY
    FROM ACTIVE DATABASE
    DORECOVER
    SPFILE
      SET db_unique_name='VERADBPRD_DR'
      SET db_create_file_dest='+DATA'
      SET db_create_online_log_dest_1='+REDO'
      SET standby_file_management='AUTO'
      SET audit_file_dest='/u01/app/oracle/admin/VERADBPRD_DR/adump'
    NOFILENAMECHECK;
}

Expected result RMAN completes the duplicate and recovery without errors.

DBA note Use NOFILENAMECHECK only when primary and standby have independent storage/file systems and the file layout makes it safe.

Validate the physical standby

SELECT NAME, DB_UNIQUE_NAME, DATABASE_ROLE,
       OPEN_MODE, CONTROLFILE_TYPE
FROM V$DATABASE;

Expected result NAME=DATAVERLABS, DB_UNIQUE_NAME=VERADBPRD_DR, DATABASE_ROLE=PHYSICAL STANDBY, OPEN_MODE=MOUNTED, CONTROLFILE_TYPE=STANDBY.

Standby redo logs (both databases)

Critical for Broker validation and real-time apply. For 5 × 10 GB primary online redo groups, create 6 × 10 GB SRLs per database, all on Thread 1.

Standby SRLs

ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 6  '+REDO' SIZE 10G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 7  '+REDO' SIZE 10G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 8  '+REDO' SIZE 10G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 9  '+REDO' SIZE 10G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 10 '+REDO' SIZE 10G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 11 '+REDO' SIZE 10G;

Primary SRLs

ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 6  '+REDO' SIZE 10G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 7  '+REDO' SIZE 10G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 8  '+REDO' SIZE 10G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 9  '+REDO' SIZE 10G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 10 '+REDO' SIZE 10G;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 11 '+REDO' SIZE 10G;
SELECT GROUP#, THREAD#, BYTES/1024/1024 AS SIZE_MB, STATUS
FROM V$STANDBY_LOG
ORDER BY GROUP#;

Expected result Six SRLs, all Thread 1, each 10,240 MB. On an active standby, one may show ACTIVE, the rest UNASSIGNED.

DBA note Do not create SRLs with THREAD#=0 for a single-thread design — see ORA-16789 in Troubleshooting.

Configure & enable Broker

Broker files in ASM — primary

ALTER SYSTEM SET DG_BROKER_CONFIG_FILE1=
'+DATA/VERADBPRD/BROKER/dr1VERADBPRD.dat'
SCOPE=SPFILE;

ALTER SYSTEM SET DG_BROKER_CONFIG_FILE2=
'+REDO/VERADBPRD/BROKER/dr2VERADBPRD.dat'
SCOPE=SPFILE;

Broker files in ASM — standby

ALTER SYSTEM SET DG_BROKER_CONFIG_FILE1=
'+DATA/VERADBPRD_DR/BROKER/dr1VERADBPRD_DR.dat'
SCOPE=SPFILE;

ALTER SYSTEM SET DG_BROKER_CONFIG_FILE2=
'+REDO/VERADBPRD_DR/BROKER/dr2VERADBPRD_DR.dat'
SCOPE=SPFILE;
ALTER SYSTEM SET DG_BROKER_START=TRUE SCOPE=BOTH;

Expected result DG_BROKER_START=TRUE on both databases; each reports its own +DATA/+REDO Broker file paths.

Create the Broker configuration:

dgmgrl /

CREATE CONFIGURATION 'DATAVERLABS_DG'
  AS PRIMARY DATABASE IS 'VERADBPRD'
  CONNECT IDENTIFIER IS 'VERADBPRD';

ADD DATABASE 'VERADBPRD_DR'
  AS CONNECT IDENTIFIER IS 'VERADBPRD_DR'
  MAINTAINED AS PHYSICAL;

EDIT DATABASE 'VERADBPRD_DR' SET PROPERTY StaticConnectIdentifier =
'(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=dataveraproddbdr.dataveralabs.local)(PORT=1610))(CONNECT_DATA=(SERVICE_NAME=VERADBPRD_DR_DGMGRL)(INSTANCE_NAME=VERADBPRD_DR)(SERVER=DEDICATED)))';

ENABLE CONFIGURATION;

DBA note Once Broker owns the configuration, avoid manually duplicating LOG_ARCHIVE_CONFIG / LOG_ARCHIVE_DEST_2 — Broker populates these itself.

Validate transport & apply

-- PRIMARY
SELECT DEST_ID, STATUS, DATABASE_MODE, RECOVERY_MODE,
       GAP_STATUS, ERROR
FROM V$ARCHIVE_DEST_STATUS
WHERE DEST_ID=2;

Expected result STATUS=VALID, DATABASE_MODE=MOUNTED-STANDBY, RECOVERY_MODE=MANAGED REAL TIME APPLY, GAP_STATUS=NO GAP, ERROR blank.

-- STANDBY
SELECT NAME, VALUE, UNIT
FROM V$DATAGUARD_STATS
WHERE NAME IN ('transport lag','apply lag','apply finish time');

Expected result Transport and apply lag are zero or within your approved operational threshold.

SHOW CONFIGURATION;
SHOW DATABASE 'VERADBPRD';
SHOW DATABASE 'VERADBPRD_DR';

Expected result: Configuration Status: SUCCESS, Fast-Start Failover: Disabled.

Planned switchover test

⚠ Production impact: Run only during an approved change window. This changes which database is primary and briefly interrupts write availability. Confirm zero/acceptable lag and a SUCCESS Broker status before proceeding. Please note: Need to execute these commands from the dgmgrl utility

SHOW CONFIGURATION;
SHOW DATABASE 'VERADBPRD';
SHOW DATABASE 'VERADBPRD_DR';

-- Primary
SELECT NAME, OPEN_MODE, DATABASE_ROLE, SWITCHOVER_STATUS
FROM V$DATABASE;

SWITCHOVER TO 'VERADBPRD_DR';

Expected result VERADBPRD_DR becomes PRIMARY, VERADBPRD becomes PHYSICAL STANDBY.

Rollback / switch back:

SWITCHOVER TO 'VERADBPRD';

SHOW CONFIGURATION;

Expected result VERADBPRD is PRIMARY again, VERADBPRD_DR is PHYSICAL STANDBY, Broker returns SUCCESS.

Troubleshooting

ORA-16789 — Standby redo logs configured incorrectly

The reference build initially had four SRLs with THREAD#=0. Broker reported ORA-16789 even though transport was functioning. Fix: recreate SRLs as Thread 1 on both primary and standby.

SELECT GROUP#, THREAD#, BYTES/1024/1024 SIZE_MB, STATUS
FROM V$STANDBY_LOG
ORDER BY GROUP#;

ORA-01156 — recovery or flashback in progress

Dropping an SRL while managed recovery is running can fail with ORA-01156. Stop apply through Broker first, and only drop a confirmed UNASSIGNED SRL.

EDIT DATABASE 'VERADBPRD_DR' SET STATE='APPLY-OFF';

TNS-03505 — Failed to resolve name

Confirm the environment and TNS entries are actually what the session is using:

echo $ORACLE_HOME
echo $TNS_ADMIN
which tnsping
grep -n -A12 -B2 "VERADBPRD_DR_DGMGRL" $TNS_ADMIN/tnsnames.ora
tnsping VERADBPRD_DR_DGMGRL

Production checklist

  • DB_NAME matches between primary and standby
  • DB_UNIQUE_NAME values are unique
  • Primary is ARCHIVELOG and FORCE_LOGGING
  • TNS connectivity works in both directions
  • Standby static Broker service is configured
  • RMAN Active Duplicate completes successfully
  • Standby is PHYSICAL STANDBY and MOUNTED
  • Primary and standby each have 6 × 10 GB SRLs on Thread 1
  • Broker configuration files are assigned to ASM
  • DG_BROKER_START=TRUE on both databases
  • Broker configuration is enabled
  • Redo transport is VALID, GAP_STATUS=NO GAP
  • Real-time apply is active; transport/apply lag within threshold
  • Fast-Start Failover is Disabled
  • Planned switchover and switchback tested (if approved)

Conclusion

This gives you a Broker-managed Oracle 19c physical standby with asynchronous redo transport and real-time apply, supporting controlled manual switchover and switchback without enabling automatic failover. Keep FSFO disabled unless your environment has a tested observer setup and an approved reason to automate role transitions.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top