Far Sync is an Oracle Data Guard feature that lets you achieve zero data loss (SYNC transport) to a remote standby database without paying the latency penalty on primary transactions. A Far Sync instance sits in a third location between the primary and the standby, receives redo synchronously from the primary (low-latency hop), and then ships it asynchronously to the standby (long-distance hop).
1. Reference Architecture
1.1 Environment Overview
| Role | Hostname | DB Unique Name | Location | OS |
|---|---|---|---|---|
| Primary DB (RAC, 2 nodes) | prim01.fra.example.com, prim02.fra.example.com |
ORCL_FRA |
Frankfurt DC (AZ-1) | OL 8.9 |
| Far Sync Instance | farsync01.fra.example.com |
ORCL_FS |
Frankfurt DC (AZ-2) | OL 8.9 |
| Physical Standby (RAC, 2 nodes) | stby01.ams.example.com, stby02.ams.example.com |
ORCL_AMS |
Amsterdam DC | OL 8.9 |
| DGMGRL / Observer host | observer01.fra.example.com |
— | Frankfurt DC (AZ-3) | OL 8.9 |
- Oracle version: 19c (19.23 RU)
- Primary ↔ Far Sync network: Dedicated 10 GbE VLAN, round-trip latency ≈ 0.4 ms
- Far Sync ↔ Standby network: WAN link, round-trip latency ≈ 8 ms
- DB_NAME:
ORCL(same for all members);DB_UNIQUE_NAMEdiffers per member
2. Live Redo Information Flow
The diagram above shows the full geographical redo flow. Below is the step-by-step explanation of how zero data loss is achieved:
Why this design achieves zero data loss
- The primary commits only after the Far Sync instance confirms the redo has been written to its standby redo log (
SYNCtransport,AFFIRM). - Because Far Sync is physically close (sub-millisecond), the commit latency impact is negligible.
- Far Sync ships the redo to the standby asynchronously (
ASYNC,NOAFFIRM), so the long-haul WAN latency does not block primary commits. - If the Far Sync instance itself fails, the primary automatically re-evaluates transport and can temporarily fall back to direct ASYNC to the standby — controlled by
MAX_FAILUREandREOPENsettings.
3. Prerequisites
3.1 OS / Network
# On ALL hosts — ensure Oracle user, groups, and limits are consistent
id oracle
# uid=54321(oracle) gid=54321(oinstall)
# Verify sub-millisecond RTT primary <-> Far Sync
ping -c 10 farsync01.fra.example.com
# Open required ports (both directions)
firewall-cmd --permanent --add-port=1521/tcp # Oracle listener
firewall-cmd --permanent --add-port=6200/tcp # Grid IPC (RAC)
firewall-cmd --reload
3.2 Oracle Software on the Far Sync Host
Far Sync requires only an Oracle Database home — no Grid Infrastructure, no actual database datafiles.
# On farsync01 — install 19c RDBMS home only (same patch level as primary)
export ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1
$ORACLE_HOME/runInstaller -silent -responseFile /tmp/db_install.rsp \
ORACLE_HOME=$ORACLE_HOME \
ORACLE_BASE=/u01/app/oracle \
oracle.install.option=INSTALL_DB_SWONLY \
DECLINE_SECURITY_UPDATES=true
4. Primary Database Configuration
4.1 init.ora / SPfile Parameters
-- Connect to primary as SYSDBA
sqlplus / as sysdba
ALTER SYSTEM SET DB_NAME='ORCL' SCOPE=SPFILE SID='*';
ALTER SYSTEM SET DB_UNIQUE_NAME='ORCL_FRA' SCOPE=SPFILE SID='*';
-- Enable Data Guard
ALTER SYSTEM SET LOG_ARCHIVE_CONFIG=
'DG_CONFIG=(ORCL_FRA,ORCL_FS,ORCL_AMS)' SCOPE=BOTH SID='*';
-- Standby redo logs (SRLs) — required on primary for role transitions
-- Size must match online redo log size; add (threads × max_log_members) + 1
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1
GROUP 11 ('/u01/oradata/ORCL/srl01a.log',
'/u02/oradata/ORCL/srl01b.log') SIZE 512M;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1
GROUP 12 ('/u01/oradata/ORCL/srl02a.log',
'/u02/oradata/ORCL/srl02b.log') SIZE 512M;
ALTER DATABASE ADD STANDBY LOGFILE THREAD 1
GROUP 13 ('/u01/oradata/ORCL/srl03a.log',
'/u02/oradata/ORCL/srl03b.log') SIZE 512M;
-- Repeat for THREAD 2 (second RAC node), groups 21-23
-- Archive log destinations
-- DEST_1: local archiving (mandatory)
ALTER SYSTEM SET LOG_ARCHIVE_DEST_1=
'LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES,ALL_ROLES)
DB_UNIQUE_NAME=ORCL_FRA' SCOPE=BOTH SID='*';
-- DEST_2: SYNC to Far Sync (the key setting)
ALTER SYSTEM SET LOG_ARCHIVE_DEST_2=
'SERVICE=ORCL_FS SYNC AFFIRM
VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE)
DB_UNIQUE_NAME=ORCL_FS
MAX_FAILURE=1 REOPEN=300
COMPRESSION=ENABLE' SCOPE=BOTH SID='*';
ALTER SYSTEM SET LOG_ARCHIVE_DEST_STATE_2=ENABLE SCOPE=BOTH SID='*';
-- DEST_3: ASYNC to standby (used only when FS is down)
ALTER SYSTEM SET LOG_ARCHIVE_DEST_3=
'SERVICE=ORCL_AMS ASYNC NOAFFIRM
VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE)
DB_UNIQUE_NAME=ORCL_AMS
DEPENDENCY=LOG_ARCHIVE_DEST_2' SCOPE=BOTH SID='*';
ALTER SYSTEM SET LOG_ARCHIVE_DEST_STATE_3=ENABLE SCOPE=BOTH SID='*';
-- Data protection
ALTER SYSTEM SET LOG_ARCHIVE_MIN_SUCCEED_DEST=1 SCOPE=BOTH SID='*';
-- Force logging (mandatory for Data Guard)
ALTER DATABASE FORCE LOGGING;
-- Remote archive
ALTER SYSTEM SET REMOTE_LOGIN_PASSWORDFILE=EXCLUSIVE SCOPE=SPFILE SID='*';
ALTER SYSTEM SET FAL_SERVER='ORCL_FS','ORCL_AMS' SCOPE=BOTH SID='*';
ALTER SYSTEM SET FAL_CLIENT='ORCL_FRA' SCOPE=BOTH SID='*';
-- Standby file management
ALTER SYSTEM SET STANDBY_FILE_MANAGEMENT=AUTO SCOPE=BOTH SID='*';
4.2 tnsnames.ora on the Primary
# /u01/app/oracle/product/19.0.0/dbhome_1/network/admin/tnsnames.ora
ORCL_FRA =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = prim01-vip.fra.example.com)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = prim02-vip.fra.example.com)(PORT = 1521))
(CONNECT_DATA = (SERVICE_NAME = ORCL_FRA)))
ORCL_FS =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = farsync01.fra.example.com)(PORT = 1521))
(CONNECT_DATA = (SERVICE_NAME = ORCL_FS)))
ORCL_AMS =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = stby01-vip.ams.example.com)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = stby02-vip.ams.example.com)(PORT = 1521))
(CONNECT_DATA = (SERVICE_NAME = ORCL_AMS)))
5. Far Sync Instance Creation
A Far Sync instance has no datafiles — only a control file, standby redo logs, and a password file. It is created via CREATE FAR SYNC INSTANCE (19c+) or by duplicating with RMAN.
5.1 Password File (copy from primary)
# On prim01 — copy the password file to the Far Sync host
scp $ORACLE_HOME/dbs/orapwORCL [email protected]:$ORACLE_HOME/dbs/orapwORCL_FS
5.2 Parameter File for the Far Sync Instance
# On farsync01 — create a minimal pfile
cat > $ORACLE_HOME/dbs/initORCL_FS.ora << 'EOF'
DB_NAME=ORCL
DB_UNIQUE_NAME=ORCL_FS
ENABLE_PLUGGABLE_DATABASE=TRUE # match primary CDB setting
LOG_ARCHIVE_CONFIG='DG_CONFIG=(ORCL_FRA,ORCL_FS,ORCL_AMS)'
# Far Sync receives from primary (VALID_FOR=STANDBY_LOGFILES)
LOG_ARCHIVE_DEST_1='LOCATION=USE_DB_RECOVERY_FILE_DEST
VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=ORCL_FS'
# Far Sync forwards to standby ASYNC
LOG_ARCHIVE_DEST_2='SERVICE=ORCL_AMS ASYNC NOAFFIRM
VALID_FOR=(STANDBY_LOGFILES,STANDBY_ROLE)
DB_UNIQUE_NAME=ORCL_AMS'
LOG_ARCHIVE_DEST_STATE_2=ENABLE
FAL_SERVER=ORCL_FRA
FAL_CLIENT=ORCL_FS
STANDBY_FILE_MANAGEMENT=AUTO
DB_RECOVERY_FILE_DEST=/u01/fra/ORCL_FS
DB_RECOVERY_FILE_DEST_SIZE=100G
REMOTE_LOGIN_PASSWORDFILE=EXCLUSIVE
EOF
5.3 Start the Far Sync Instance and Create the Control File
-- On farsync01 as SYSDBA
export ORACLE_SID=ORCL_FS
sqlplus / as sysdba
STARTUP NOMOUNT PFILE='$ORACLE_HOME/dbs/initORCL_FS.ora';
-- Create the Far Sync control file (run on farsync01, referencing primary)
-- This is a STANDBY control file; no datafiles needed
CREATE FAR SYNC INSTANCE CONTROLFILE AS
'/u01/fra/ORCL_FS/ORCL_FS_control01.ctl';
-- Mount it
ALTER DATABASE MOUNT;
-- Add Standby Redo Logs on the Far Sync instance
-- Match the primary's online redo log size and count
ALTER DATABASE ADD STANDBY LOGFILE GROUP 11
'/u01/fra/ORCL_FS/srl11.log' SIZE 512M;
ALTER DATABASE ADD STANDBY LOGFILE GROUP 12
'/u01/fra/ORCL_FS/srl12.log' SIZE 512M;
ALTER DATABASE ADD STANDBY LOGFILE GROUP 13
'/u01/fra/ORCL_FS/srl13.log' SIZE 512M;
ALTER DATABASE ADD STANDBY LOGFILE GROUP 14
'/u01/fra/ORCL_FS/srl14.log' SIZE 512M;
-- Far Sync is single-instance so THREAD 1 only
-- Convert the listener to register the Far Sync service
-- /etc/oratab entry: ORCL_FS:/u01/app/oracle/product/19.0.0/dbhome_1:N
5.4 Listener on farsync01
# listener.ora on farsync01
LISTENER_FS =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = farsync01.fra.example.com)(PORT = 1521))))
SID_LIST_LISTENER_FS =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = ORCL_FS)
(ORACLE_HOME = /u01/app/oracle/product/19.0.0/dbhome_1)
(SID_NAME = ORCL_FS)))
lsnrctl start LISTENER_FS
lsnrctl status LISTENER_FS
6. Physical Standby Database
6.1 Duplicate from Primary Using RMAN Active Duplication
# Run from the standby host (stby01) as oracle user
rman target sys/SYS_PASSWORD@ORCL_FRA auxiliary sys/SYS_PASSWORD@ORCL_AMS
DUPLICATE TARGET DATABASE FOR STANDBY FROM ACTIVE DATABASE
SPFILE
SET DB_UNIQUE_NAME='ORCL_AMS'
SET LOG_ARCHIVE_CONFIG='DG_CONFIG=(ORCL_FRA,ORCL_FS,ORCL_AMS)'
SET LOG_ARCHIVE_DEST_1='LOCATION=USE_DB_RECOVERY_FILE_DEST
VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=ORCL_AMS'
SET LOG_ARCHIVE_DEST_2='SERVICE=ORCL_FRA ASYNC NOAFFIRM
VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=ORCL_FRA'
SET FAL_SERVER='ORCL_FS','ORCL_FRA'
SET FAL_CLIENT='ORCL_AMS'
SET STANDBY_FILE_MANAGEMENT='AUTO'
SET DB_RECOVERY_FILE_DEST='/u01/fra/ORCL_AMS'
SET DB_RECOVERY_FILE_DEST_SIZE='500G'
NOFILENAMECHECK;
6.2 Start Managed Recovery on the Standby
-- On stby01 as SYSDBA
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
-- Verify apply is running
SELECT PROCESS, STATUS, THREAD#, SEQUENCE#, BLOCK#
FROM V$MANAGED_STANDBY
ORDER BY PROCESS;
7. DGMGRL Configuration
7.1 Create the Broker Configuration
# On observer01 (or any host with tnsnames configured)
dgmgrl sys/SYS_PASSWORD@ORCL_FRA
DGMGRL> CREATE CONFIGURATION 'DG_ORCL'
AS PRIMARY DATABASE IS 'ORCL_FRA'
CONNECT IDENTIFIER IS ORCL_FRA;
DGMGRL> ADD FAR_SYNC 'ORCL_FS'
AS CONNECT IDENTIFIER IS ORCL_FS;
DGMGRL> ADD DATABASE 'ORCL_AMS'
AS CONNECT IDENTIFIER IS ORCL_AMS
MAINTAINED AS PHYSICAL;
DGMGRL> ENABLE CONFIGURATION;
7.2 Configure Redo Routes
The Broker “redo route” tells it the intended transport path. The Far Sync instance is the relay.
DGMGRL> EDIT DATABASE 'ORCL_FRA' SET PROPERTY
RedoRoutes = '(LOCAL : ORCL_FS SYNC AFFIRM)';
DGMGRL> EDIT FAR_SYNC 'ORCL_FS' SET PROPERTY
RedoRoutes = '(ORCL_FRA : ORCL_AMS ASYNC NOAFFIRM)';
-- Protection mode: MAXIMUM AVAILABILITY (zero data loss via Far Sync)
DGMGRL> EDIT CONFIGURATION SET PROTECTION MODE AS MAXAVAILABILITY;
DGMGRL> SHOW CONFIGURATION;
Expected output:
Configuration - DG_ORCL
Protection Mode: MaxAvailability
Members:
ORCL_FRA - Primary database
ORCL_FS - Far sync instance
ORCL_AMS - Physical standby database
Fast-Start Failover: Disabled
Configuration Status:
SUCCESS (status updated 8 seconds ago)
7.3 Enable Fast-Start Failover (FSFO)
-- Set target and thresholds
DGMGRL> EDIT CONFIGURATION SET PROPERTY
FastStartFailoverThreshold = 30; -- seconds
DGMGRL> EDIT CONFIGURATION SET PROPERTY
FastStartFailoverTarget = 'ORCL_AMS';
DGMGRL> ENABLE FAST_START FAILOVER;
-- Start the observer (keep running — use nohup or a dedicated service)
DGMGRL> START OBSERVER FILE='/u01/fsfo/observer_DG_ORCL.dat'
LOGFILE='/u01/fsfo/observer_DG_ORCL.log';
8. Verification
8.1 Redo Transport Lag and Apply Lag
-- On the primary
SELECT DEST_ID, DEST_NAME, STATUS, TARGET, ARCHIVER,
SCHEDULE, DESTINATION, APPLIED_SCN,
TRANSMIT_MODE, NET_TIMEOUT, MAX_FAILURE, REOPEN_SECS
FROM V$ARCHIVE_DEST
WHERE TARGET = 'STANDBY'
ORDER BY DEST_ID;
-- Lag check via Data Guard V$ views (on primary)
SELECT NAME, VALUE, UNIT, TIME_COMPUTED
FROM V$DATAGUARD_STATS
WHERE NAME IN ('transport lag','apply lag','apply finish time');
8.2 Far Sync Health
-- On the Far Sync instance
SELECT PROCESS, STATUS, THREAD#, SEQUENCE#
FROM V$MANAGED_STANDBY;
-- Confirm it is in FAR SYNC role
SELECT DB_UNIQUE_NAME, DATABASE_ROLE, OPEN_MODE
FROM V$DATABASE;
-- Expected: FAR SYNC | MOUNTED
8.3 DGMGRL Status
DGMGRL> SHOW CONFIGURATION VERBOSE;
DGMGRL> SHOW DATABASE VERBOSE 'ORCL_FRA';
DGMGRL> SHOW DATABASE VERBOSE 'ORCL_AMS';
DGMGRL> SHOW FAR_SYNC VERBOSE 'ORCL_FS';
DGMGRL> VALIDATE FAR_SYNC 'ORCL_FS';
8.4 Switchover Test
DGMGRL> VALIDATE DATABASE 'ORCL_AMS';
DGMGRL> SWITCHOVER TO 'ORCL_AMS';
-- After switchover:
DGMGRL> SHOW CONFIGURATION;
-- ORCL_AMS is now primary; ORCL_FRA is physical standby
-- Switchover back:
DGMGRL> SWITCHOVER TO 'ORCL_FRA';
9. Far Sync Failure Handling
When the Far Sync instance fails, the primary automatically re-evaluates LOG_ARCHIVE_DEST_2. Because MAX_FAILURE=1 and DEPENDENCY is set on DEST_3, the primary switches to direct ASYNC transport to the standby (DEST_3), temporarily trading zero-data-loss for availability. This transition is seamless and logged in the alert log.
-- Check current effective transport mode during FS outage
SELECT DEST_ID, STATUS, TARGET, TRANSMIT_MODE, ERROR
FROM V$ARCHIVE_DEST
WHERE TARGET = 'STANDBY';
-- Monitor recovery from alert log
ALTER SYSTEM SET LOG_ARCHIVE_DEST_STATE_2 = ENABLE; -- re-enables after FS comes back
When the Far Sync instance recovers, it catches up from the primary’s archived logs (FAL fetch), and the primary’s REOPEN=300 timer ensures it will re-try DEST_2 within 5 minutes.
10. Tips and Best Practices
- Same patch level everywhere. Far Sync, primary, and standby must run identical Oracle version and RU. Patch Far Sync in rolling fashion like any other member.
- Standby Redo Log sizing. Add at least
(max_online_log_groups + 1)SRLs per thread on every member, sized to match the online redo logs exactly. - Far Sync is CPU-light. It only processes redo headers and forwards log files — a VM with 2 vCPU / 8 GB RAM is sufficient for most workloads.
- Place the observer in a third fault domain. The observer on
observer01.fra.example.com(AZ-3) must not share fate with the primary or Far Sync; otherwise FSFO cannot reliably distinguish a primary failure from a network partition. - Encryption in transit. Enable Oracle Net encryption (
sqlnet.ora/SQLNET.ENCRYPTION_SERVER=REQUIRED) on all members to protect redo in flight over the WAN. - Monitor with Enterprise Manager or DGMGRL health checks scheduled via a cron job:
dgmgrl -silent sys/... @/dba/scripts/dg_healthcheck.dgmgrl.