poor man data guard
if you are working on oracle XE Database and you want to create DR for it but XE is limited then you can apply this steps
oraclesqlbashhigh-availabilityv1.0.0
0 stars1 downloads44 views1 comments
By Mahmoud • Created
Code
(245 lines)123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
1 - edit the tnsnames on Primary
-------------------------------# Create / update tnsnames.ora
on PRIMARY :
vi tnsnames.ora
# tnsnames.ora Network Configuration File: /opt/oracle/homes/OraDBHome21cXE/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.
PRIMARY =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.159.128)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = XE)
)
)
LISTENER_XE =
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
XEPDB1 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.159.140)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = XEPDB1)
)
)
DR =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.159.139)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = XE)
)
)
2 - edit the tnsnames on DR
----------------------------
on DR :
vi tnsnames.ora
# tnsnames.ora Network Configuration File: /opt/oracle/homes/OraDBHome21cXE/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.
DR =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.159.139)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = XE)
)
)
LISTENER_XE =
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
XEPDB1 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.159.139)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = XEPDB1)
)
)
PRIMARY =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.159.128)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = XE)
)
)
3 - on DR edit LISTENER
--------------------
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.159.139)(PORT = 1521))
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
)
)
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = XE)
(ORACLE_HOME = /opt/oracle/product/21c/dbhomeXE)
(GLOBAL_DBNAME = XE)
)
)
DEFAULT_SERVICE_LISTENER = XE
==============================================================================
4 - On Primary – Enable ARCHIVELOG + FORCE LOGGING
sqlplus / as sysdba
SQL > SHUTDOWN IMMEDIATE;
SQL > STARTUP MOUNT;
SQL > ALTER DATABASE ARCHIVELOG;
SQL > ALTER DATABASE FORCE LOGGING;
SQL > ALTER DATABASE OPEN;
-- Verify
ARCHIVE LOG LIST;
SELECT FORCE_LOGGING, LOG_MODE FROM V$DATABASE;
SELECT DESTINATION FROM V$ARCHIVE_DEST WHERE STATUS='VALID';
ALTER SYSTEM SET LOG_ARCHIVE_DEST_1='LOCATION=/opt/oracle/archivelogs' SCOPE=BOTH;
show parameter log_archive_format='arch_%t_%s_%r.arc' -- make sure that the format end with .arc
==============================================================================
5 - on Primar and DR create password file
orapwd file=$ORACLE_HOME/dbs/orapwXE password=sys entries=10 force=y format=12
==============================================================================
6 - On DR VM – Prepare the auxiliary instance
Bash# Create a small pfile for NOMOUNT (only if RMAN asks for it)
cat > /tmp/initXE.ora <<EOF
*.db_name='XE'
*.compatible='21.0.0'
EOF
# Start in NOMOUNT
sqlplus / as sysdba
STARTUP NOMOUNT PFILE='/tmp/initXE.ora';
EXIT
==============================================================================
7 - On Primary VM – RMAN Active Duplicate (20 GB over network, ~fast on VMs)
rman target sys/sys auxiliary sys/sys@DR
RMAN > DUPLICATE TARGET DATABASE
FOR STANDBY
FROM ACTIVE DATABASE
DORECOVER
SPFILE
SET DB_UNIQUE_NAME = 'XE_DR'
SET DB_FILE_NAME_CONVERT '/opt/oracle/oradata/XE/', '/opt/oracle/oradata/XE/'
SET LOG_FILE_NAME_CONVERT '/opt/oracle/oradata/XE/', '/opt/oracle/oradata/XE/'
COMMENT 'Clean physical standby - 14-Apr-2026'
NOFILENAMECHECK;
==============================================================================
8. Verify on DR (should be running in standby mode)
sqlplus / as sysdba
SELECT DB_UNIQUE_NAME, OPEN_MODE, DATABASE_ROLE FROM V$DATABASE;
-- Expected: XE_DR MOUNTED PHYSICAL STANDBY
SELECT SEQUENCE#, APPLIED FROM V$ARCHIVED_LOG ORDER BY SEQUENCE# DESC;
-- make sure that this parameters same as primary
show parameter LOG_ARCHIVE_DEST_1 -- same as primary
show parameter log_archive_format -- same as primary
==============================================================================
9 - run the rsync command on primary to sync the archives between them
rsync -avz --include='*.arc' --exclude='*' /opt/oracle/archivelogs/ [email protected]:/opt/oracle/archivelogs/
==============================================================================
10 - on DR apply the change
RMAN> CATALOG START WITH '/opt/oracle/archivelogs/' NOPROMPT;
--output
searching for all files that match the pattern /opt/oracle/archivelogs/
List of Files Unknown to the Database
=====================================
File Name: /opt/oracle/archivelogs/arch_1_2_1230481113.arc
File Name: /opt/oracle/archivelogs/arch_1_3_1230481113.arc
File Name: /opt/oracle/archivelogs/arch_1_4_1230481113.arc
File Name: /opt/oracle/archivelogs/arch_1_5_1230481113.arc
File Name: /opt/oracle/archivelogs/arch_1_6_1230481113.arc
File Name: /opt/oracle/archivelogs/arch_1_7_1230481113.arc
File Name: /opt/oracle/archivelogs/arch_1_8_1230481113.arc
cataloging files...
cataloging done
List of Cataloged Files
=======================
File Name: /opt/oracle/archivelogs/arch_1_2_1230481113.arc
File Name: /opt/oracle/archivelogs/arch_1_3_1230481113.arc
File Name: /opt/oracle/archivelogs/arch_1_4_1230481113.arc
File Name: /opt/oracle/archivelogs/arch_1_5_1230481113.arc
File Name: /opt/oracle/archivelogs/arch_1_6_1230481113.arc
File Name: /opt/oracle/archivelogs/arch_1_7_1230481113.arc
File Name: /opt/oracle/archivelogs/arch_1_8_1230481113.arc
RMAN> RECOVER DATABASE;
--output
Starting recover at 14-APR-26
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=417 device type=DISK
starting media recovery
archived log for thread 1 with sequence 8 is already on disk as file /opt/oracle/archivelogs/arch_1_8_1230481113.arc
archived log file name=/opt/oracle/archivelogs/arch_1_8_1230481113.arc thread=1 sequence=8
media recovery complete, elapsed time: 00:00:25
Finished recover at 14-APR-26
=============================================================================
11 - Failover – run on DR only when disaster hits
SQL > sqlplus / as sysdba
ALTER DATABASE ACTIVATE STANDBY DATABASE;
ALTER DATABASE OPEN;
#Your DR is now the new primary (read-write).
#Quick checks after everything is running
#On DR (daily monitoring):
SQL >
SELECT SEQUENCE#, APPLIED FROM V$ARCHIVED_LOG ORDER BY SEQUENCE# DESC;
SELECT NAME, VALUE FROM V$DATAGUARD_STATS;
-- to go back
sqlplus / as sysdba
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
Then:
SQL >
ALTER DATABASE CONVERT TO PHYSICAL STANDBY;
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
-- then repet steps 9 , 10Usage Instructions
this is step by step from scratch on test environment