Monday, March 23, 2026

RMAN ACTIVE DUPLICATE — RUNNER DOC

 


RMAN ACTIVE DUPLICATE — RUNNER DOC

Oracle 19c  |  Target → Auxiliary (DR Clone)

# Env: OL7.9 / 19.3.0.0.0

 * Note: This test is done in my lab machine, I will suggest first try in your lab for the test, then use it.

Environment reference

 

# SOURCE (TARGET)

ORACLE_SID=FINPRD

DB_NAME=FINPRD

ORACLE_HOME=/u01/app/oracle/product/19.3.0/dbhome_1

ORACLE_BASE=/u01/app/oracle

HOST=ora-prod-01.corp.internal

TNS_ALIAS=FINPRD

 

# DESTINATION (AUXILIARY / DR)

ORACLE_SID=FINDR

DB_NAME=FINDR

ORACLE_HOME=/u01/app/oracle/product/19.3.0/dbhome_1

ORACLE_BASE=/u01/app/oracle

HOST=ora-dr-01.corp.internal

TNS_ALIAS=FINDR

 

# PATHS — auxiliary host

ORADATA=/data01/oradata/FINDR

FRA=/fra01/FINDR

ADMIN=/u01/app/oracle/admin/FINDR

 

# RMAN SYS password  →  do NOT hardcode in prod, use wallet

# SYS_PWD=<get from vault or /etc/oracle/.sys_cred>

 

 Pre Check – Source host

[01] Verify source DB — open mode, archivelog, force logging

sqlplus / as sysdba

 

SELECT name, open_mode, log_mode, force_logging FROM v$database;

 

→ expected output:

SQL> SELECT name, open_mode, log_mode, force_logging FROM v$database;

 

NAME      OPEN_MODE            LOG_MODE     FOR

--------- -------------------- ------------ ---

FINPRD    READ WRITE           ARCHIVELOG   YES

 

1 row selected.

 

# WARNING: If FOR=NO  →  ALTER DATABASE FORCE LOGGING;  then re-check.

 

[02] Check source listener — FINPRD must show READY

# On ora-prod-01.corp.internal

lsnrctl status LISTENER

 

tnsping FINPRD

 

→ expected (relevant lines only):

Service "FINPRD" has 1 instance(s).

  Instance "FINPRD", status READY, has 1 handler(s) for this service...

 

TNS Ping Utility for Linux: Version 19.0.0.0.0

OK (10 msec)

 

# WARNING: If FINPRD shows BLOCKED or UNKNOWN — DB is not fully open. Do not proceed.

 

OS PREPARATION  —  AUXILIARY HOST

[03] Set env — run this first in every new shell session

# ssh oracle@ora-dr-01.corp.internal

 

export ORACLE_SID=FINDR

export ORACLE_BASE=/u01/app/oracle

export ORACLE_HOME=/u01/app/oracle/product/19.3.0/dbhome_1

export PATH=$ORACLE_HOME/bin:$PATH

export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH

 

# quick sanity

echo $ORACLE_SID && which sqlplus && which rman

 

→ expected:

FINDR

/u01/app/oracle/product/19.3.0/dbhome_1/bin/sqlplus

/u01/app/oracle/product/19.3.0/dbhome_1/bin/rman

 

[04] Create directory structure on auxiliary

# WARNING: Run as root or oracle with sudo. RMAN will ORA-01119 if these don't exist.

 

mkdir -p /data01/oradata/FINDR

mkdir -p /fra01/FINDR

mkdir -p /u01/app/oracle/admin/FINDR/adump

mkdir -p /u01/app/oracle/admin/FINDR/dpdump

mkdir -p /u01/app/oracle/admin/FINDR/hdump

 

chown -R oracle:oinstall /data01/oradata /fra01

chmod -R 755 /data01/oradata /fra01 /u01/app/oracle/admin/FINDR

 

# verify

ls -ld /data01/oradata/FINDR /fra01/FINDR /u01/app/oracle/admin/FINDR/adump

 

→ all 3 lines should show oracle:oinstall ownership:

drwxr-xr-x 2 oracle oinstall 6 Nov 12 09:14 /data01/oradata/FINDR

drwxr-xr-x 2 oracle oinstall 6 Nov 12 09:14 /fra01/FINDR

drwxr-xr-x 2 oracle oinstall 6 Nov 12 09:14 /u01/app/oracle/admin/FINDR/adump

 

[05] Create password file — must match SYS password on source

# password must match ora-prod-01 SYS password exactly

orapwd file=$ORACLE_HOME/dbs/orapwFINDR \

        password=<SYS_PASSWORD> \

        entries=5 \

        force=y \

        format=12

 

ls -lh $ORACLE_HOME/dbs/orapwFINDR

 

→ expected:

-rw-r----- 1 oracle oinstall 2.0K Nov 12 09:16 /u01/app/oracle/product/19.3.0/dbhome_1/dbs/orapwFINDR

 

# WARNING: ORA-01017 during RMAN connect = password mismatch. Recreate orapwd with correct password.

 

[06] Create minimal pfile — just enough for NOMOUNT


# INFO: Only parameters needed for NOMOUNT. RMAN will set the rest from source spfile during duplicate. 


cat > $ORACLE_HOME/dbs/initFINDR.ora << 'EOF'

db_name=FINDR

db_unique_name=FINDR

sga_target=2G

pga_aggregate_target=512M

db_block_size=8192

enable_pluggable_database=false

audit_file_dest=/u01/app/oracle/admin/FINDR/adump

diagnostic_dest=/u01/app/oracle

EOF

 

cat $ORACLE_HOME/dbs/initFINDR.ora

 

# INFO: If source is CDB → set enable_pluggable_database=true

 

[07] Start auxiliary in NOMOUNT

sqlplus / as sysdba

 

STARTUP NOMOUNT PFILE='/u01/app/oracle/product/19.3.0/dbhome_1/dbs/initFINDR.ora';

 

→ expected:

SQL> STARTUP NOMOUNT PFILE='...';

ORACLE instance started.

 

Total System Global Area 2147483648 bytes

Fixed Size                  8900952 bytes

Variable Size             503316480 bytes

Database Buffers         1627389952 bytes

Redo Buffers                7876608 bytes

 

-- validate instance came up

SELECT instance_name, status FROM v$instance;

-- Expected: FINDR   STARTED

 

TNS + LISTENER  —  AUXILIARY HOST

[08] Add both aliases to tnsnames.ora on auxiliary

vi $ORACLE_HOME/network/admin/tnsnames.ora

# --- append these entries ---

 

FINPRD =

  (DESCRIPTION =

    (ADDRESS = (PROTOCOL = TCP)(HOST = ora-prod-01.corp.internal)(PORT = 1521))

    (CONNECT_DATA =

      (SERVER = DEDICATED)

      (SERVICE_NAME = FINPRD)

    )

  )

 

FINDR =

  (DESCRIPTION =

    (ADDRESS = (PROTOCOL = TCP)(HOST = ora-dr-01.corp.internal)(PORT = 1521))

    (CONNECT_DATA =

      (SERVER = DEDICATED)

      (SERVICE_NAME = FINDR)

    )

  )

 

[09] Configure STATIC listener entry — required while DB is NOMOUNT

# WARNING: Dynamic registration won't work in NOMOUNT. Static SID_LIST entry is mandatory or RMAN connection will fail.

 

vi $ORACLE_HOME/network/admin/listener.ora

 

LISTENER =

  (DESCRIPTION_LIST =

    (DESCRIPTION =

      (ADDRESS = (PROTOCOL = TCP)(HOST = ora-dr-01.corp.internal)(PORT = 1521))

    )

  )

 

SID_LIST_LISTENER =

  (SID_LIST =

    (SID_DESC =

      (GLOBAL_DBNAME = FINDR)

      (ORACLE_HOME = /u01/app/oracle/product/19.3.0/dbhome_1)

      (SID_NAME = FINDR)

    )

  )

 

lsnrctl stop LISTENER

lsnrctl start LISTENER

lsnrctl status LISTENER | grep -A2 'Service\|SID'

 

→ FINDR will show UNKNOWN — that is normal for static entry in NOMOUNT:

Service "FINDR" has 1 instance(s).

  Instance "FINDR", status UNKNOWN, has 1 handler(s) for this service...

 

[10] Validate TNS + actual login to source before running RMAN

tnsping FINPRD   # must be OK

tnsping FINDR    # must be OK

 

# test real connection to source

sqlplus sys/<SYS_PASSWORD>@FINPRD as sysdba

SELECT name, open_mode FROM v$database;

EXIT;

 

# WARNING: If tnsping OK but sqlplus fails → firewall blocking 1521, or wrong password. Fix before RMAN.

 

RMAN ACTIVE DUPLICATE

[11] Connect RMAN to both target and auxiliary

# run from ora-dr-01 (auxiliary host)

rman

 

CONNECT TARGET sys/<SYS_PASSWORD>@FINPRD;

CONNECT AUXILIARY sys/<SYS_PASSWORD>@FINDR;

 

→ expected:

Recovery Manager: Release 19.0.0.0.0 - Production

 

connected to target database: FINPRD (DBID=3421876501)

connected to auxiliary database: FINDR (not mounted)

 

# WARNING: ORA-12541 → listener not running or static entry missing (re-check step 09).

# WARNING: ORA-01017 → password file wrong or not created (re-check step 05).

 

[12] Execute DUPLICATE — monitor alert log in parallel session

# INFO: Open a second SSH session now and tail the alert log before hitting run.

 

# --- SECOND TERMINAL (monitor) ---

tail -100f /u01/app/oracle/diag/rdbms/findr/FINDR/trace/alert_FINDR.log

 

# --- RMAN SESSION (step 11 continued) ---

RUN {

  ALLOCATE CHANNEL c1 TYPE DISK;

  ALLOCATE CHANNEL c2 TYPE DISK;

  ALLOCATE AUXILIARY CHANNEL a1 TYPE DISK;

  ALLOCATE AUXILIARY CHANNEL a2 TYPE DISK;

 

  DUPLICATE TARGET DATABASE TO FINDR

    FROM ACTIVE DATABASE

    SPFILE

      PARAMETER_VALUE_CONVERT 'FINPRD','FINDR',

                               '/data01/oradata/FINPRD','/data01/oradata/FINDR',

                               '/fra01/FINPRD','/fra01/FINDR'

      SET DB_UNIQUE_NAME='FINDR'

      SET DB_NAME='FINDR'

      SET INSTANCE_NAME='FINDR'

      SET AUDIT_FILE_DEST='/u01/app/oracle/admin/FINDR/adump'

      SET DIAGNOSTIC_DEST='/u01/app/oracle'

      SET DB_FILE_NAME_CONVERT

          '/data01/oradata/FINPRD','/data01/oradata/FINDR'

      SET LOG_FILE_NAME_CONVERT

          '/data01/oradata/FINPRD','/data01/oradata/FINDR'

      SET LOG_ARCHIVE_DEST_1='LOCATION=/fra01/FINDR'

      SET CONTROL_FILES='/data01/oradata/FINDR/control01.ctl',

                        '/fra01/FINDR/control02.ctl'

    NOFILENAMECHECK;

}

 

→ last line on success:

Finished Duplicate Db at 12-NOV-2024 11:43:07

 

# ORA-19505 / ORA-17628  →  disk space issue on auxiliary paths

# ORA-01119              →  directory missing, re-check step 04

# Channel drops mid-run  →  network instability or NET_TIMEOUT too low

#   workaround: add to RMAN config →  CONFIGURE CHANNEL DEVICE TYPE DISK PARAMS 'NET_TIMEOUT=300';

 

POST-DUPLICATE STEPS

 

 

[13] Confirm DB opened — check role, mode, log_mode

sqlplus / as sysdba

 

SELECT name, db_unique_name, open_mode, log_mode, database_role

FROM   v$database;

 

→ expected:

NAME   DB_UNIQUE_NAME  OPEN_MODE   LOG_MODE   DATABASE_ROLE

------ --------------- ----------- ---------- ----------------

FINDR  FINDR           READ WRITE  ARCHIVELOG PRIMARY

 

[14] Confirm SPFILE is active — not running off pfile

SELECT value FROM v$parameter WHERE name = 'spfile';

-- must return non-null path

 

-- also check on OS

ls -lh $ORACLE_HOME/dbs/spfileFINDR.ora

 

# WARNING: If spfile value is NULL → RMAN didn't apply SPFILE clause. Check duplicate command, re-run.

 

[15] Verify all files are on auxiliary paths — no FINPRD leftover

-- must return ZERO rows

SELECT 'datafile' src, name FROM v$datafile  WHERE name LIKE '%FINPRD%'

UNION ALL

SELECT 'tempfile' src, name FROM v$tempfile   WHERE name LIKE '%FINPRD%'

UNION ALL

SELECT 'logfile'  src, member FROM v$logfile  WHERE member LIKE '%FINPRD%';

 

-- if rows returned → file rename needed before production use

 

→ expected:

no rows selected

 

[16] Check redo logs + tempfiles are online

SELECT group#, status, members FROM v$log ORDER BY 1;

-- one group should be CURRENT, others INACTIVE/UNUSED

 

SELECT file#, name, status FROM v$tempfile;

-- status should be ONLINE

 

[17] Check invalid objects + registry

SELECT count(*) invalid_obj FROM dba_objects WHERE status='INVALID';

-- compare vs source; minor count is acceptable if same on source

 

SELECT comp_name, version, status FROM dba_registry ORDER BY comp_name;

-- all components should be VALID

 

[18] Force listener re-registration + confirm READY

ALTER SYSTEM REGISTER;

 

-- wait 30 sec then:

-- (from OS)

lsnrctl status LISTENER | grep -A2 FINDR

 

→ after registration (was UNKNOWN in step 09, now should be READY):

Service "FINDR" has 1 instance(s).

  Instance "FINDR", status READY, has 1 handler(s) for this service...

 

[19] Take immediate backup of controlfile + spfile

rman target /

 

BACKUP CURRENT CONTROLFILE FORMAT '/fra01/FINDR/cf_%d_%T_%s.bkp';

BACKUP SPFILE FORMAT '/fra01/FINDR/spfile_%d_%T_%s.bkp';

 

LIST BACKUP SUMMARY;

 

FINAL VALIDATION  —  PASTE & RUN

 

sqlplus / as sysdba << 'EOF'

 

set linesize 120 pagesize 50

 

prompt === 1. DB IDENTITY ===

SELECT name, db_unique_name, created FROM v$database;

 

prompt === 2. OPEN MODE + ROLE ===

SELECT open_mode, database_role, log_mode FROM v$database;

 

prompt === 3. INSTANCE STATUS ===

SELECT instance_name, status, database_status FROM v$instance;

 

prompt === 4. REDO LOG STATUS ===

SELECT group#, status, members, bytes/1048576 mb FROM v$log ORDER BY 1;

 

prompt === 5. TEMP TABLESPACE ===

SELECT tablespace_name, status FROM dba_tablespaces WHERE contents='TEMPORARY';

 

prompt === 6. CONTROLFILE STATUS ===

SELECT name, status FROM v$controlfile;

 

prompt === 7. SPFILE IN USE ===

SELECT value FROM v$parameter WHERE name='spfile';

 

prompt === 8. ARCHIVE DEST STATUS ===

SELECT dest_name, status, target FROM v$archive_dest WHERE status='VALID';

 

prompt === 9. INVALID OBJECTS COUNT ===

SELECT count(*) invalid_count FROM dba_objects WHERE status='INVALID';

 

prompt === 10. CURRENT SCN ===

SELECT current_scn FROM v$database;

 

EXIT;

EOF

 

# OS-level sanity

ps -ef | grep pmon | grep -i findr    # ora_pmon_FINDR must be running

lsnrctl status | grep FINDR           # status READY expected

 

# END OF RUNNER DOC

# Rev: 1.0  |  Tested: 19.3.0.0.0 / OL7.9  

 

Oracle Autonomous Database Internals: What Is Really Automated

Oracle Autonomous Database Internals: What Is Really Automated

Oracle Autonomous Database Internals: What Is Really Automated

Beyond the Marketing - What ADB Actually Does vs What DBAs Still Own
23 March 2026
Chetan Yadav — Senior Oracle & Cloud DBA
⏱️ 13–14 min read
⏱️ Estimated Reading Time: 13–14 minutes
ADW • ATP • Auto-Indexing • Auto-Patching • Auto-Scaling • What DBAs Still Own
Oracle Autonomous Database architecture diagram showing ADW ATP workload types automation engine and DBA responsibilities
⚙️ Environment Referenced in This Article

Service: Oracle Autonomous Database on OCI (Shared & Dedicated Exadata Infrastructure)
Workload Types Tested: ADW, ATP, AJD  •  Oracle DB Version: 19c base + 23ai features on ADB
Workload: 2.8 TB OLTP + 6.1 TB analytics  •  Scale: 4–32 ECPU auto-scaling  •  Region: OCI ap-mumbai-1 primary, ap-hyderabad-1 DR

"The self-driving database." Oracle's marketing for Autonomous Database promises that the DBA is no longer needed — the database manages itself. Patches itself. Tunes itself. Scales itself. After running Oracle ADB in production for financial and analytics workloads across multiple OCI regions, I can tell you the reality is more nuanced and more interesting than the marketing suggests.

Oracle Autonomous Database genuinely automates things that used to consume enormous DBA time — patching, backup, storage management, and a meaningful subset of performance tuning. But it does not eliminate the need for database expertise. It changes what that expertise is applied to. The DBA who understands what ADB actually automates and what it does not will be dramatically more effective than one who takes the "self-driving" claim at face value.

This guide opens the hood on Oracle ADB internals: how auto-indexing actually works, what happens inside auto-patching, when auto-scaling kicks in, and which critical responsibilities remain firmly with the DBA and architect.

Monday, March 16, 2026

Step-by-step installation of Oracle Database 19c (64-bit) on Red Hat Enterprise Linux 9.4

Oracle Database 19c Installation Runner

Platform: RHEL 9.4 (64-bit)


Step-by-step installation of Oracle Database 19c (64-bit) on Red Hat Enterprise Linux 9.4.


1. Assumed the Installer is downloaded 

File name:

LINUX.X64_193000_db_home.zip

Upload it to the server 

/stage/oracle/LINUX.X64_193000_db_home.zip


2.  Configure Hostname

hostname.

hostnamectl


3. Configure /etc/hosts

Edit hosts file.

vi /etc/hosts


4. Install Oracle Preinstall Package

Configure prerequisites 

dnf install -y oracle-database-preinstall-19c


*Note :(this pre install steps will automatically create the require user, group and required lib and rpm)


5. Configure SELinux

Edit SELinux configuration.

vi /etc/selinux/config

Set:

SELINUX=permissive

Apply immediately:

setenforce 0


6.  Disable Firewall

Stop firewall.

systemctl stop firewalld

systemctl disable firewalld


7. Create Oracle Directory Structure

Create Oracle installation directories using your custom path.

mkdir -p /Chetan/practice/u01/app/oracle/product/19.0.0/dbhome_1

mkdir -p /Chetan/practice/u02/oradata

Set ownership.

chown -R oracle:oinstall /Chetan

chmod -R 775 /Chetan


8.  Configure Oracle Environment

Login as oracle user.

su - oracle

Create scripts directory.

mkdir ~/scripts

Create environment script.

vi ~/scripts/setEnv.sh

Add:

export TMP=/tmp

export TMPDIR=$TMP


export ORACLE_HOSTNAME=rhel9-oracle.localdomain


export ORACLE_BASE=/Chetan/practice/u01/app/oracle

export ORACLE_HOME=$ORACLE_BASE/product/19.0.0/dbhome_1


export ORACLE_SID=cdb1

export PDB_NAME=pdb1


export DATA_DIR=/Chetan/practice/u02/oradata


export PATH=$ORACLE_HOME/bin:$PATH

export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib

Load environment automatically.

echo ". ~/scripts/setEnv.sh" >> ~/.bash_profile

Reload profile.

source ~/.bash_profile

 


9. Extract Oracle Software

Navigate to Oracle Home.

cd /Chetan/practice/u01/app/oracle/product/19.0.0/dbhome_1

Unzip software.

unzip -oq /stage/oracle/LINUX.X64_193000_db_home.zip


10 . Run Oracle Installer

Start installer.

./runInstaller

Select:

Install Database Software Only

Edition: Enterprise Edition

Oracle Base:

/Chetan/practice/u01/app/oracle

Oracle Home:

/Chetan/practice/u01/app/oracle/product/19.0.0/dbhome_1

________________________________________


11. Start Oracle Listener

Switch to oracle user.

Start listener.

lsnrctl start

Verify listener.

lsnrctl status

________________________________________

12. Create Database Using DBCA

Run Database Configuration Assistant.

dbca

Select:

Create Database

General Purpose Database

Create Container Database

Example configuration:

SID:

cdb1

PDB:

pdb1

 

Datafile location:

/Chetan/practice/u02/oradata


13. Verify Database

Connect to database.

sqlplus / as sysdba

Check database.

select name, open_mode from v$database;

Check PDB.

show pdbs;



Installation Completed

Oracle Database 19c is now successfully installed.

Oracle Home:

/Chetan/practice/u01/app/oracle/product/19.0.0/dbhome_1

Database files:

/Chetan/practice/u02/oradata


Oracle Database 23ai Architecture: AI-Native Internals for DBAs

Oracle Database 23ai Architecture: AI-Native Internals for DBAs

Oracle Database 23ai Architecture: AI-Native Internals for DBAs

What Actually Changed Inside the Engine — Beyond the Marketing
16 March 2026
Chetan Yadav — Senior Oracle & Cloud DBA
⏱️ 11–12 min read
⏱️ Estimated Reading Time: 11–12 minutes
AI Vector Search • Select AI • JSON Duality • True Cache • SQL Domains • Lock-Free Reservations
Oracle Database 23ai complete AI-native architecture diagram showing AI layer, SQL engine, security, core engine, HA/DR and connectivity
⚙️ Environment Used in This Article

Oracle Database: 23ai (23.4) Enterprise Edition  •  Platform: Oracle Linux 8.9 on OCI & on-premises x86
Workload: Mixed OLTP + AI/ML vector search workloads  •  DB Size: 4.2 TB
New Features Tested: AI Vector Search, Select AI, JSON Duality Views, True Cache, SQL Domains, Lock-Free Reservations, Boolean datatype, Schema Privileges

Oracle called it "23ai" for a reason. This is not a routine point release with incremental improvements. The AI suffix signals a deliberate architectural shift — Oracle has embedded AI capabilities directly into the database engine itself, not as an external add-on or middleware layer.

But for DBAs and architects the most important question is not "what did Oracle announce?" It is "what actually changed inside the engine, and what does that mean for how I design, tune, and operate my databases?" The marketing materials will tell you Oracle 23ai is revolutionary. This guide will tell you which features are genuinely production-ready, which ones still need maturity, and what the internal architecture changes mean for your workload.

I have tested Oracle 23ai extensively on both OCI and on-premises environments running real OLTP and vector workloads. This guide reflects what I found in practice, not what the release notes promise.

Thursday, March 12, 2026

Oracle Data Guard Protection Modes: Zero Data Loss Design Strategy

Oracle Data Guard Protection Modes: Zero Data Loss Design Strategy

Oracle Data Guard Protection Modes: Zero Data Loss Design Strategy

Production HA/DR Architecture for DBAs and Architects
12 March 2026
Chetan Yadav — Senior Oracle & Cloud DBA
⏱️ 12–13 min read
⏱️ Estimated Reading Time: 12–13 minutes
Maximum Protection • Maximum Availability • Maximum Performance — Choose Wisely
Oracle Data Guard Protection Modes architecture diagram showing Primary, Standby, GCS, GES, redo transport and RPO RTO comparison
⚙️ Production Environment Referenced in This Article

Oracle Database: 19.18.0.0.0 & 23ai Enterprise Edition  •  Data Guard Broker: Enabled with Fast-Start Failover
Primary: 2-Node RAC, 6 TB OLTP  •  Standby: Physical Standby, separate data center (120 km)
Network: Dedicated 10 GbE WAN link  •  RTO Target: < 30 seconds  •  RPO Target: Zero data loss
Application: Core banking transaction processing system

2:14 AM. A storage array at the primary data center suffered a catastrophic controller failure. The entire primary RAC cluster went offline. No warning. No graceful shutdown. Just gone.

Within 23 seconds, Oracle Data Guard Fast-Start Failover had detected the outage, confirmed quorum with the observer, and automatically activated the physical standby database. The application connection pool reconnected. Transactions resumed. The on-call team received the alert after the failover had already completed.

That outcome — 23 seconds, zero data loss, no manual intervention — was not luck. It was the result of choosing the right Data Guard protection mode, designing the redo transport correctly, and validating failover under load before the incident happened. Most organizations running Data Guard never validate their failover until disaster strikes. By then it is too late to discover the configuration was wrong.

This guide explains Oracle Data Guard protection modes in depth: what each mode actually guarantees, how redo transport works under the hood, when to use each mode, and the production design decisions that determine whether your standby database saves you or fails you at the worst possible moment.

1. Data Guard Architecture: How It Actually Works

Oracle Data Guard maintains one or more synchronized copies of a primary database called standby databases. When the primary fails, a standby can take over as the new primary — either automatically via Fast-Start Failover or manually via a DBA-initiated failover command.

The core mechanism is redo log shipping. Every change made to the primary database is recorded in redo logs. Data Guard ships those redo records to the standby in real time, where they are applied to keep the standby synchronized.

Key Data Guard Components

ComponentLocationRole
LGWR / DMONPrimaryCaptures redo and initiates shipping to standby
NSA / NSS ProcessPrimaryNetwork Server process — sends redo over the network
RFS ProcessStandbyRemote File Server — receives redo from primary
MRP ProcessStandbyManaged Recovery Process — applies redo to standby
LSP ProcessStandby (logical)LogMiner Server Process — applies SQL for logical standby
DMON ProcessBothData Guard Monitor — manages broker configuration
ObserverThird siteMonitors primary for Fast-Start Failover quorum
SQL — Verify Data Guard Configuration Status
-- Check Data Guard status on primary SELECT name, db_unique_name, database_role, protection_mode, protection_level, switchover_status, dataguard_broker FROM v$database; -- Check redo transport status to all standbys SELECT dest_id, dest_name, status, target, archiver, schedule, destination, applied_scn, error FROM v$archive_dest WHERE status != 'INACTIVE' ORDER BY dest_id; -- Check standby apply lag SELECT name, value, datum_time FROM v$dataguard_stats WHERE name IN ('transport lag', 'apply lag', 'apply finish time') ORDER BY name;

2. The Three Protection Modes Explained

Oracle Data Guard offers three protection modes. Each makes a different trade-off between data loss guarantee, performance impact, and availability. Choosing the wrong mode for your workload is one of the most common — and most dangerous — Data Guard mistakes.

Maximum Protection

Every redo record must be written to at least one standby redo log on the standby database before the primary acknowledges the transaction commit. If the standby becomes unreachable, the primary database shuts itself down rather than risk any data divergence.

  • Transport: SYNC — synchronous redo shipping
  • Affirm: AFFIRM — standby must confirm disk write
  • RPO: Zero — absolutely no data loss under any failure scenario
  • RTO: Fast — standby is fully synchronized at all times
  • Risk: Primary shuts down if standby is unreachable — availability depends on standby health
  • Use case: Regulatory compliance, core banking, financial settlement systems
Production Reality — Maximum Protection:

A core banking client ran Maximum Protection mode. During a routine standby server reboot for OS patching, the primary database shut itself down — taking the entire production system offline for 18 minutes. The team had forgotten that Maximum Protection means the primary cannot run without the standby. Always maintain a second standby or use Maximum Availability instead for most production workloads.

Maximum Availability

The default recommended mode for most production systems. Like Maximum Protection, it uses synchronous redo shipping. However, if the standby becomes unreachable, the primary automatically falls back to asynchronous mode and continues running. When the standby reconnects, it resynchronizes and the primary returns to synchronous mode automatically.

  • Transport: SYNC — synchronous when standby is available
  • Affirm: AFFIRM — confirms disk write on standby
  • RPO: Zero under normal conditions; seconds of exposure during fallback
  • RTO: Fast — standby synchronized within seconds of primary failure
  • Risk: Brief data loss window during the fallback period
  • Use case: Enterprise OLTP, e-commerce, healthcare systems

Maximum Performance

The default mode when Data Guard is first configured. Redo is shipped asynchronously — the primary does not wait for the standby to confirm receipt before acknowledging the commit. This provides the best primary performance but at the cost of a potential data loss window.

  • Transport: ASYNC — asynchronous redo shipping
  • Affirm: NOAFFIRM — no standby disk write confirmation required
  • RPO: Seconds to minutes depending on network latency and redo volume
  • RTO: Fast but standby may lag behind primary
  • Risk: Data loss equal to the apply lag at time of failure
  • Use case: Reporting standbys, development/test environments, geographically distant DR sites
SQL — Change Protection Mode (via Data Guard Broker)
-- Connect to DGMGRL as SYSDG or SYSDBA -- dgmgrl sys/password@primary -- Check current protection mode SHOW CONFIGURATION; SHOW DATABASE VERBOSE primary_db; -- Change to Maximum Availability (recommended for most production) EDIT CONFIGURATION SET PROTECTION MODE AS MAXAVAILABILITY; -- Change to Maximum Protection (zero data loss, primary shuts down without standby) EDIT CONFIGURATION SET PROTECTION MODE AS MAXPROTECTION; -- Change to Maximum Performance (async, best performance) EDIT CONFIGURATION SET PROTECTION MODE AS MAXPERFORMANCE; -- Verify after change SHOW CONFIGURATION;

3. Redo Transport Deep Dive: SYNC vs ASYNC

The protection mode you choose determines the redo transport mechanism. Understanding the difference between SYNC and ASYNC transport is essential for making the right design choice.

Synchronous Transport (SYNC)

With synchronous transport, the primary database Log Writer (LGWR) process sends the redo record to the standby at the same time it writes to the local online redo log. The commit does not complete until both the local write and the standby acknowledgment have been received. This introduces latency equal to the round-trip time between primary and standby.

Network Latency Rule for SYNC Transport

For synchronous redo transport, the round-trip network latency between primary and standby should be under 5 ms for OLTP workloads. Beyond 5 ms, commit latency becomes noticeable to applications. Beyond 20 ms, SYNC transport typically causes unacceptable performance degradation. In our production environment with a 120 km dark fiber link, round-trip latency is 1.8 ms — well within acceptable range for Maximum Availability mode.

Asynchronous Transport (ASYNC)

With asynchronous transport, the primary LGWR writes to the local redo log and acknowledges the commit immediately. A separate background process (NSA — Network Server Async) ships redo to the standby independently. The standby typically lags behind the primary by the amount of redo generated during the network transfer time.

SQL — Configure Redo Transport (LOG_ARCHIVE_DEST)
-- Maximum Availability: SYNC transport with AFFIRM ALTER SYSTEM SET log_archive_dest_2 = 'SERVICE=standby_db SYNC AFFIRM NET_TIMEOUT=30 VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=standby_db' SCOPE=BOTH SID='*'; -- Maximum Performance: ASYNC transport with NOAFFIRM ALTER SYSTEM SET log_archive_dest_2 = 'SERVICE=standby_db ASYNC NOAFFIRM NET_TIMEOUT=30 VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=standby_db' SCOPE=BOTH SID='*'; -- Verify redo transport configuration SELECT dest_id, dest_name, target, archiver, net_timeout, affirm, async_blocks, status FROM v$archive_dest WHERE dest_id = 2;

Standby Redo Logs (SRL) — Critical Requirement

Standby Redo Logs (SRLs) are required for real-time apply and for synchronous transport. They must be the same size as the primary online redo logs and there must be at least one more SRL group per thread than the number of online redo log groups on the primary.

SQL — Add Standby Redo Logs on Standby Database
-- Check existing online redo log sizes on primary SELECT group#, members, bytes/1024/1024 AS size_mb, status FROM v$log ORDER BY group#; -- Add standby redo logs on standby (same size, one extra group per thread) -- For a 2-node RAC primary with 3 redo groups per thread: -- Add 4 SRL groups per thread (3 + 1 = 4) ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 11 ('+DATA/stdby/srl_t1_g11.log') SIZE 200M; ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 12 ('+DATA/stdby/srl_t1_g12.log') SIZE 200M; ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 13 ('+DATA/stdby/srl_t1_g13.log') SIZE 200M; ALTER DATABASE ADD STANDBY LOGFILE THREAD 1 GROUP 14 ('+DATA/stdby/srl_t1_g14.log') SIZE 200M; -- Verify SRL configuration SELECT group#, thread#, sequence#, bytes/1024/1024 AS size_mb, archived, status FROM v$standby_log ORDER BY thread#, group#;

4. Standby Database Types: Physical vs Logical vs Snapshot

TypeApply MethodOpen for Reads?Best Use Case
Physical Standby Block-for-block redo apply (MRP) Yes (Active Data Guard, extra license) Primary DR target, zero data loss
Logical Standby SQL Apply via LogMiner (LSP) Yes (read/write, some restrictions) Reporting, DDL testing, heterogeneous environments
Snapshot Standby Redo buffered but not applied Yes (full read/write) Testing, QA, patch validation against production data
DGMGRL — Convert Physical Standby to Snapshot Standby
-- Convert to snapshot standby (opens for read/write, buffers redo) CONVERT DATABASE standby_db TO SNAPSHOT STANDBY; -- Verify conversion SHOW DATABASE standby_db; -- Convert back to physical standby (discards all changes, resumes apply) CONVERT DATABASE standby_db TO PHYSICAL STANDBY;

5. Fast-Start Failover: Automatic DR Activation

Fast-Start Failover (FSFO) enables Oracle Data Guard to automatically fail over to the standby database without any DBA intervention when the primary becomes unavailable. This is what enabled the 23-second failover described in the introduction.

FSFO Requirements

  • Data Guard Broker must be enabled and configured
  • Observer process running on a third independent host
  • Protection mode must be Maximum Availability or Maximum Protection
  • Standby Redo Logs must be configured on the standby
  • Flashback Database recommended for reinstating the old primary
DGMGRL — Configure Fast-Start Failover
-- Enable Fast-Start Failover ENABLE FAST_START FAILOVER; -- Set failover threshold (seconds primary must be unreachable before failover) EDIT CONFIGURATION SET PROPERTY FastStartFailoverThreshold = 30; -- Set lag limit (max apply lag allowed when FSFO is enabled) EDIT CONFIGURATION SET PROPERTY FastStartFailoverLagLimit = 30; -- Start the observer (run on third independent host) -- dgmgrl sys/password@primary START OBSERVER; -- Verify FSFO configuration SHOW FAST_START FAILOVER; SHOW CONFIGURATION VERBOSE; -- Simulate failover for testing (without data loss) -- Run from observer host FAILOVER TO standby_db;
Production FSFO Design Tip:

Always run the FSFO observer on a third independent host — not on the primary server and not on the standby server. If both the primary and the observer are on the same network segment and that segment fails, the standby may not receive quorum to activate FSFO. In our production setup, the observer runs on a small VM in a separate availability zone with network access to both primary and standby. Test FSFO every quarter by deliberately shutting down the primary during a low-traffic window.

6. Active Data Guard: Read-Only Standby While Applying Redo

Active Data Guard (ADG) allows the physical standby database to be open in read-only mode while redo apply continues in the background. This means the standby can serve reporting queries, offload read traffic from the primary, and still be ready to fail over at any moment.

Licensing Note

Active Data Guard requires the Oracle Active Data Guard option, which is a separately licensed Enterprise Edition add-on. A physical standby open in read-only mode without redo apply is available without ADG license. Real-time redo apply while open read-only requires the ADG license. Always verify licensing before enabling ADG in production.
SQL — Enable Active Data Guard (Real-Time Apply + Read-Only)
-- On standby database: open read-only with real-time apply ALTER DATABASE OPEN READ ONLY; ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT FROM SESSION; -- Verify ADG status SELECT open_mode, database_role, db_unique_name FROM v$database; -- Monitor apply lag on ADG standby SELECT name, value, unit, time_computed FROM v$dataguard_stats WHERE name IN ('transport lag', 'apply lag', 'apply finish time', 'estimated startup time') ORDER BY name; -- Check active sessions using standby for reads SELECT COUNT(*) AS read_sessions, module, action FROM gv$session WHERE status = 'ACTIVE' AND type = 'USER' GROUP BY module, action ORDER BY read_sessions DESC FETCH FIRST 10 ROWS ONLY;

7. Data Guard Broker: Centralized Configuration Management

Data Guard Broker provides a unified interface for managing the entire Data Guard configuration. Without Broker, you manage each database individually through LOG_ARCHIVE_DEST parameters and manual commands. With Broker, you manage the entire configuration through a single DGMGRL command-line interface.

SQL & DGMGRL — Data Guard Broker Setup and Health Check
-- Enable Data Guard Broker on both primary and standby ALTER SYSTEM SET dg_broker_start = TRUE SCOPE=BOTH SID='*'; -- Connect to broker (run on primary or standby) -- dgmgrl / -- Create broker configuration CREATE CONFIGURATION dg_config AS PRIMARY DATABASE IS primary_db CONNECT IDENTIFIER IS primary_db; -- Add standby database to configuration ADD DATABASE standby_db AS CONNECT IDENTIFIER IS standby_db MAINTAINED AS PHYSICAL; -- Enable the configuration ENABLE CONFIGURATION; -- Full health check SHOW CONFIGURATION; SHOW DATABASE VERBOSE primary_db; SHOW DATABASE VERBOSE standby_db; -- Validate configuration (checks for issues proactively) VALIDATE DATABASE primary_db; VALIDATE DATABASE standby_db;
DGMGRL — Switchover (Planned Role Transition)
-- Switchover: planned, zero data loss, reversible -- Use for maintenance, patching, or DR testing -- Verify configuration is ready for switchover VALIDATE DATABASE primary_db; SHOW CONFIGURATION; -- Initiate switchover to standby SWITCHOVER TO standby_db; -- After switchover: verify new primary is active SHOW CONFIGURATION; SHOW DATABASE VERBOSE standby_db; -- now primary SHOW DATABASE VERBOSE primary_db; -- now standby -- Switchover back when maintenance is complete SWITCHOVER TO primary_db;

8. Real Production Failover: What Actually Happens

These are real Data Guard incidents from production environments and the lessons they produced.

Incident 1: Protection Mode Mismatch Caused Silent Data Loss

A financial services client had Data Guard configured but in Maximum Performance mode (the default). They believed they had zero data loss protection. During a primary storage failure, the standby was 47 seconds behind the primary due to ASYNC transport lag. 47 seconds of financial transactions were permanently lost.

Lesson: Always verify protection mode AND transport mode with SELECT protection_mode, protection_level FROM v$database. The protection_level column shows the actual effective mode — it differs from protection_mode when the standby has fallen back to async.
Incident 2: Standby Redo Logs Not Configured — Real-Time Apply Silently Disabled

A team set up Data Guard correctly — or so they thought. Failover testing revealed the standby was 8 hours behind the primary. Investigation showed Standby Redo Logs had never been created. Without SRLs, real-time apply cannot function and the standby only catches up during log archive shipping, leaving a massive gap.

Lesson: Always verify SRLs exist and are active: SELECT * FROM v$standby_log. If this view is empty, real-time apply is not running.
Success: 23-Second Automatic Failover (The Introduction Story)

Configuration that made it work: Maximum Availability mode, SYNC/AFFIRM transport on 1.8 ms latency link, Standby Redo Logs sized identically to primary, FSFO enabled with threshold of 15 seconds, observer on independent host, Flashback Database enabled on both primary and standby, and quarterly failover testing under full production load.

Key lesson: Fast-Start Failover only works reliably when every component is validated together under real load — not just configured and assumed to work.
SQL — Data Guard Health Check Queries
-- 1. Verify effective protection mode (must match intended mode) SELECT name, db_unique_name, database_role, protection_mode, -- configured mode protection_level -- actual effective mode (may differ) FROM v$database; -- 2. Check transport lag and apply lag SELECT name, value, datum_time FROM v$dataguard_stats WHERE name IN ('transport lag', 'apply lag') ORDER BY name; -- 3. Verify standby redo logs exist and are active SELECT group#, thread#, sequence#, bytes/1024/1024 AS size_mb, archived, status FROM v$standby_log ORDER BY thread#, group#; -- 4. Check MRP (apply) process is running on standby SELECT process, status, thread#, sequence#, block#, blocks FROM v$managed_standby WHERE process LIKE 'MRP%' OR process LIKE 'RFS%' ORDER BY process;

9. Protection Mode Decision Framework

Use this framework to choose the right protection mode for your workload.

Choose Maximum Protection if ALL of these are true:

  • Regulatory zero data loss is a hard legal requirement (banking, finance, government)
  • You have a second standby or can tolerate primary shutdown if standby fails
  • Network latency between primary and standby is under 2 ms
  • Your application can tolerate slightly higher commit latency

Choose Maximum Availability if ANY of these are true:

  • You need near-zero data loss but cannot accept primary shutdown risk
  • Network latency is under 5 ms and workload is standard OLTP
  • You want Fast-Start Failover with automatic activation
  • This is your primary DR configuration for an enterprise system

Choose Maximum Performance if ANY of these are true:

  • This standby is for reporting or dev/test only — not primary DR
  • The standby is geographically distant (WAN latency > 10 ms)
  • Some data loss is acceptable and primary performance is the priority
  • You are running a second standby in addition to a sync standby

10. FAQ

What is the difference between Switchover and Failover?
Switchover is a planned, graceful role transition. Both primary and standby participate cooperatively. There is zero data loss and the operation is fully reversible. Use switchover for planned maintenance, patching, or DR testing.

Failover is an unplanned activation of the standby when the primary is unavailable. Data loss depends on the protection mode in effect at the time. The old primary must be reinstated (using Flashback Database) before it can rejoin as a standby. Fast-Start Failover automates this process.
Does Data Guard protect against logical corruption?
No. Data Guard replicates every redo record including those caused by user errors like accidental DROP TABLE or DELETE without WHERE. The corruption is applied to the standby within seconds. For protection against logical corruption, use Flashback Database (which can rewind both primary and standby to a point before the error) or maintain a time-delayed standby using the DELAY parameter in LOG_ARCHIVE_DEST.
Can Data Guard work with Oracle RAC on the primary?
Yes. RAC primary with a single-instance physical standby is a very common and fully supported architecture. The standby receives redo from all RAC threads and applies them in order. The standby can also be a RAC database for maximum availability on both sides. This RAC + Data Guard combination is called MAA (Maximum Availability Architecture) — Oracle's reference architecture for mission-critical systems.
How often should I test failover?
At minimum, quarterly — and ideally monthly for critical systems. Test under realistic load, not during off-peak hours with zero activity. A failover that works at 2 AM with no users connected may fail at 2 PM under full load due to session cleanup issues, long-running transactions, or application reconnection pool exhaustion. Document RTO measurements from every test and track them over time.
Should I mention Data Guard on my resume?
Absolutely — with specifics. Instead of "Oracle Data Guard experience," write: "Designed and maintained Oracle Data Guard Maximum Availability configuration with Fast-Start Failover for a 6 TB core banking database. Achieved RTO of 23 seconds and RPO of zero through SYNC/AFFIRM transport on dedicated 10 GbE WAN link. Conducted quarterly failover validation under production load." Metrics and architecture decisions demonstrate real expertise.

About the Author

Chetan Yadav

Chetan Yadav is a Senior Oracle, PostgreSQL, MySQL, and Cloud DBA with 15+ years of hands-on experience managing production databases across on-premises, hybrid, and cloud environments. He specializes in high availability architecture, performance tuning, disaster recovery, and database migrations.

Throughout his career, Chetan has designed and implemented Oracle Data Guard configurations for mission-critical systems in finance, healthcare, and e-commerce sectors. He has architected zero data loss DR solutions with sub-30-second RTO targets and validated them through real failover testing under production load.

This blog focuses on real-world DBA problems, career growth, and practical learning — not theoretical documentation or vendor marketing.