Here I am going to setup a real time table data synchronization between two Oracle Databases located in different locations. We are using here the SymmetricDS community version for data replication, SymmetricDS is open source software that is free to use. It includes command line tools, documentation, and example configuration files for getting setup and running. The community provides support through the project website, forums, and issue tracker.

Environment details

 SourceTarget 
Instance TypeProductionReporting
Oracle Database versionOracle 12c EE Oracle 18c XE
DB Schema NameCRM01CRM
Operating SystemOracle Linux 7.3Oracle Linux 7.8
Symetric DS VersionSymmetricDS 3.12.1SymmetricDS 3.12.1
Symetric DS Location/u04/symmetric-server-3.12.1//home/oracle/symds/symmetric-server-3.12.1
IP Address10.111.111.19110.121.121.191

We will install SymmetricDS on two servers One on production and other on target. One will represent the Source server and one will represent the Target server. Each installed copy of SymmetricDS will be responsible for one database, and thus each copy acts as a single “node” in SymmetricDS terminology. This is the most common configuration of SymmetricDS – one installed copy of the software is responsible for one single database and represents one node.

Download Latest version of the symmetricds from the symmetricds website https://www.symmetricds.org/

INSTALLATION STEPS

On source(Production) , I have copied the symmetricsds zip file on /u04 and on target to /home/oracle/. After copying the binary login to servers as Oracle user and execute below commands
On Source -> Production DB with 12c EE
cd /u04/
unzip symmetric-server-3.12.1.zip
chown -R oracle:oinstall /u04/symmetric-server-3.12.1
chmod 775 /u04/symmetric-server-3.12.1

On Target -> Reporting DB server with 18c XE
mkdir -p /home/oracle/symds/
cd /home/oracle/symds/
unzip symmetric-server-3.12.1.zip
chown -R oracle:oinstall /home/oracle/symds/symmetric-server-3.12.1
chmod 775 /home/oracle/symds/symmetric-server-3.12.1

on Source we need mainly look in to two configuration files symmetric-server.properties & sym_service.conf, files located under conf folder on symetricds location. I have used the default parameter configuration and copied sample engine property from sample folder and create a source-000.properties under engines folder

ls -lrth

[oracle@MRCPRDBI-ORCL01 conf]$ pwd
/u04/symmetric-server-3.12.1/conf

[oracle@MRCPRDBI-ORCL01 conf]$ cat symmetric-server.properties
#
Licensed to JumpMind Inc under one or more contributor
license agreements. See the NOTICE file distributed
with this work for additional information regarding
copyright ownership. JumpMind Inc licenses this file
to you under the GNU General Public License, version 3.0 (GPLv3)
(the “License”); you may not use this file except in compliance
with the License.
#
You should have received a copy of the GNU General Public License,
version 3.0 (GPLv3) along with this library; if not, see
http://www.gnu.org/licenses/.
#
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
“AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
#
Specify the hostname/IP address to bind to. (Default 0.0.0.0 will bind to all interfaces.)
#
host.bind.name=0.0.0.0
Enable synchronization over HTTP.
#
http.enable=true
Port number for synchronization over HTTP.
#
http.port=31415
Enable synchronization over HTTPS (HTTP over SSL).
#
https.enable=false
Enable HTTPS/2 for multiplexing and resistance to protocol attacks.
#
https2.enable=false
Port number for synchronization over HTTPS (HTTP over SSL).
#
https.port=31417
Use a trust manager that allows self-signed server SSL certificates.
#
https.allow.self.signed.certs=true
List host names that are allowed for server SSL certificates.
#
https.verified.server.names=all
auto.registration = true
Accept cookies if load balancer requires it for clustering
#
server.http.cookies.enabled=false

cat sym_service.conf
#*****************************
# Wrapper Java Properties
#*****************************
# Java Runtime Executable
wrapper.java.command=java

#Java Classpath
wrapper.java.classpath.1=patches
wrapper.java.classpath.2=patches/*
wrapper.java.classpath.3=lib/.jar wrapper.java.classpath.4=web/WEB-INF/lib/.jar

# Java Additional Parameters
wrapper.java.additional=-Dlog4j2.configurationFile=file:conf/log4j2.xml
wrapper.java.additional=-Djava.util.logging.config.file=conf/logging.properties
wrapper.java.additional=-Dsym.keystore.file=security/keystore
wrapper.java.additional=-Djavax.net.ssl.trustStore=security/cacerts
wrapper.java.additional=-Djavax.net.ssl.keyStorePassword=obf:cHVuYXRydmc=
wrapper.java.additional=-Dorg.eclipse.jetty.server.Request.maxFormContentSize=800000
wrapper.java.additional=-Dorg.eclipse.jetty.server.Request.maxFormKeys=100000
wrapper.java.additional=-Djava.io.tmpdir=tmp
wrapper.java.additional=-Dsun.net.client.defaultReadTimeout=300000
wrapper.java.additional=-Dsun.net.client.defaultConnectTimeout=300000
wrapper.java.additional=-Dfile.encoding=utf-8
wrapper.java.additional=-XX:+HeapDumpOnOutOfMemoryError
wrapper.java.additional=-XX:HeapDumpPath=tmp
wrapper.java.additional=-Djava.net.preferIPv4Stack=true
wrapper.java.additional=-Dcom.sun.management.jmxremote
wrapper.java.additional=-Dcom.sun.management.jmxremote.authenticate=false
wrapper.java.additional=-Dcom.sun.management.jmxremote.port=31418
wrapper.java.additional=-Dcom.sun.management.jmxremote.rmi.port=31418
wrapper.java.additional=-Dcom.sun.management.jmxremote.ssl=false
wrapper.java.additional=-Djava.rmi.server.hostname=localhost
wrapper.java.additional=-Dcom.ibm.as400.access.AS400.guiAvailable=false
wrapper.java.additional=-Dsymmetric.concurrent.engines.starting.count=5
wrapper.java.additional=-Dsymmetric.ssl.ignore.ciphers=TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA

# Initial Java Heap Size (in MB)
wrapper.java.initmemory=256

#Maximum Java Heap Size (in MB)
wrapper.java.maxmemory=1024

# Wrapper Application Properties
#Application main class and arguments
wrapper.app.parameter.1=org.jumpmind.symmetric.SymmetricLauncher

# This how long Jetty will wait until timing out on an HTTP response
# This value must be greater than the send.ack.keepalive.ms parameter
wrapper.app.parameter.2=–max-idle-time=90000

Wrapper Logging Properties

# Log file to use for wrapper output logging.
wrapper.logfile=logs/wrapper.log

# Wrapper process ID
wrapper.pidfile=tmp/wrapper.pid

# SymmetricDS process ID
wrapper.server.pidfile=tmp/server.pid

# Log level (SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST)
wrapper.logfile.loglevel=INFO

# Size of log file when it will rotate to next file
wrapper.logfile.maxsize=10m

# Number of log files to rotate and keep
wrapper.logfile.maxfiles=3

#Wrapper Service Properties

# Name of the service
wrapper.name=SymmetricDS

# Display name of the service
wrapper.displayname=SymmetricDS

#Description of the service
wrapper.description=Database Synchronization

#Wrapper Windows NT/2000/XP Service Properties

# Mode in which the service is installed. Auto, manual, or delay.
wrapper.ntservice.starttype=delay

# Service dependencies. Use + prefix for groups.
wrapper.ntservice.dependency.1=

# First failure action (NONE, RESTART, RUN_COMMAND)
wrapper.ntservice.failure.action.type.1=RESTART

# Milliseconds to wait before performing the action
wrapper.ntservice.failure.action.delay.1=10000

# Second failure action (NONE, RESTART, RUN_COMMAND)
wrapper.ntservice.failure.action.type.2=NONE

# Milliseconds to wait before performing the action
wrapper.ntservice.failure.action.delay.2=0

# Subsequent failure action (NONE, RESTART, RUN_COMMAND)
wrapper.ntservice.failure.action.type.3=NONE

# Milliseconds to wait before performing the action
wrapper.ntservice.failure.action.delay.3=0

# Seconds after which to reset the failure count to zero
wrapper.ntservice.failure.reset.period=300

#For failure action type RUN_COMMAND, the command line to run
wrapper.ntservice.failure.action.command=

[oracle@MRCPRDBI-ORCL01 ~]$ cd /u04/symmetric-server-3.12.1/engines/
Key configuration parameters

db.driver=oracle.jdbc.driver.OracleDriver
db.url=jdbc:oracle:thin:@10.111.111.191:1521:mrcprdb
db.user=crm01
db.password=crm01
registration.url=http://10.111.111.191:31415/sync/source-000
sync.url=http://10.111.111.191:31415/sync/source-000
group.id=source
external.id=000

Full source-000.properties

[oracle@MRCPRDBI-ORCL01 engines]$ cat source-000.properties
# Licensed to JumpMind Inc under one or more contributor
# license agreements. See the NOTICE file distributed
# with this work for additional information regarding
# copyright ownership. JumpMind Inc licenses this file
# to you under the GNU General Public License, version 3.0 (GPLv3)
# (the “License”); you may not use this file except in compliance
# with the License.
#
# You should have received a copy of the GNU General Public License,
# version 3.0 (GPLv3) along with this library; if not, see
# http://www.gnu.org/licenses/.
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Friendly name to refer to this node from command line
engine.name=source-000
# The class name for the JDBC Driver
# db.driver=com.mysql.jdbc.Driver
db.driver=oracle.jdbc.driver.OracleDriver
# db.driver=org.postgresql.Driver
# db.driver=org.apache.derby.jdbc.EmbeddedDriver
# db.driver=org.hsqldb.jdbcDriver
# db.driver=net.sourceforge.jtds.jdbc.Driver
# db.driver=com.ibm.db2.jcc.DB2Driver
# db.driver=com.informix.jdbc.IfxDriver
# db.driver=org.firebirdsql.jdbc.FBDriver
# db.driver=interbase.interclient.Driver
# db.driver=org.sqlite.JDBC
# db.driver=com.sybase.jdbc4.jdbc.SybDriver
# db.driver=com.nuodb.jdbc.Driver
# db.driver=org.h2.Driver

# The JDBC URL used to connect to the database
# db.url=jdbc:mysql://localhost/store001?tinyInt1isBit=false
db.url=jdbc:oracle:thin:@10.111.111.191:1521:mrcprdb
# db.url=jdbc:postgresql://localhost/store001?stringtype=unspecified
# db.url=jdbc:derby:store001;create=true
# db.url=jdbc:hsqldb:file:store001;shutdown=true
# db.url=jdbc:jtds:sqlserver://localhost:1433/store001;useCursors=true;bufferMaxMemory=10240;lobBuffer=5242880
# db.url=jdbc:db2://localhost/store001
#db.url=jdbc:informix-sqli://localhost:9088/store001:INFORMIXSERVER=ol_ids_1150_1
# db.url=jdbc:firebirdsql:localhost:/var/lib/firebird/data/databasename
#db.url=jdbc:interbase://localhost//opt/interbase/data/store001.gdb
# db.url=jdbc:sqlite:store001.sqlite
# db.url=jdbc:sybase:Tds:localhost:5000/databasename
# db.url=jdbc:com.nuodb://localhost/database?schema=database
# db.url=jdbc:h2:store001;AUTO_SERVER=TRUE;LOCK_TIMEOUT=60000
# The database user that SymmetricDS should use.
db.user=crm01
# The database password
db.password=crm01

# This node will contact the root node’s sync.url to register itself.
registration.url=http://10.111.111.191:31415/sync/source-000

sync.url=http://10.111.111.191:31415/sync/source-000
# Node group this node belongs to, which defines what it will sync with who.
#Must match the sym_node_group configuration in database.
group.id=source
# External ID for this node, which is any unique identifier you want to use.
external.id=000
# How to run routing (in millis), which puts changes into batches.
job.routing.period.time.ms=5000
# How often to run push (in millis), which sends changes to other nodes.
job.push.period.time.ms=10000
# How often to run pull (in millis), which receives changes from other nodes.
job.pull.period.time.ms=10000

On target we will create file dest-001.properties under engines directory

Key parameter for dest-001.properties

db.url=jdbc:oracle:thin:@10.121.121.191:1521:XE
db.user=crm
db.password=crm
registration.url=http://10.111.111.191:31415/sync/source-000
sync.url=http://10.121.121.191:31415/sync/dest-001
group.id=dest
external.id=001

# Licensed to JumpMind Inc under one or more contributor
# license agreements. See the NOTICE file distributed
# with this work for additional information regarding
# copyright ownership. JumpMind Inc licenses this file
# to you under the GNU General Public License, version 3.0 (GPLv3)
# (the “License”); you may not use this file except in compliance
# with the License.
#
# You should have received a copy of the GNU General Public License,
# version 3.0 (GPLv3) along with this library; if not, see
# http://www.gnu.org/licenses/.
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Friendly name to refer to this node from command line
engine.name=dest-001
# The class name for the JDBC Driver
# db.driver=com.mysql.jdbc.Driver
db.driver=oracle.jdbc.driver.OracleDriver
# db.driver=org.postgresql.Driver
# db.driver=org.apache.derby.jdbc.EmbeddedDriver
# db.driver=org.hsqldb.jdbcDriver
# db.driver=net.sourceforge.jtds.jdbc.Driver
# db.driver=com.ibm.db2.jcc.DB2Driver
# db.driver=com.informix.jdbc.IfxDriver
# db.driver=org.firebirdsql.jdbc.FBDriver
# db.driver=interbase.interclient.Driver
# db.driver=org.sqlite.JDBC
# db.driver=com.sybase.jdbc4.jdbc.SybDriver
# db.driver=com.nuodb.jdbc.Driver
# db.driver=org.h2.Driver

# The JDBC URL used to connect to the database
# db.url=jdbc:mysql://localhost/store001?tinyInt1isBit=false
db.url=jdbc:oracle:thin:@10.121.121.191:1521:XE
# db.url=jdbc:postgresql://localhost/store001?stringtype=unspecified
# db.url=jdbc:derby:store001;create=true
# db.url=jdbc:hsqldb:file:store001;shutdown=true
# db.url=jdbc:jtds:sqlserver://localhost:1433/store001;useCursors=true;bufferMaxMemory=10240;lobBuffer=5242880
# db.url=jdbc:db2://localhost/store001
# db.url=jdbc:informix-sqli://localhost:9088/store001:INFORMIXSERVER=ol_ids_1150_1
# db.url=jdbc:firebirdsql:localhost:/var/lib/firebird/data/databasename
# db.url=jdbc:interbase://localhost//opt/interbase/data/store001.gdb
# db.url=jdbc:sqlite:store001.sqlite
# db.url=jdbc:sybase:Tds:localhost:5000/databasename
# db.url=jdbc:com.nuodb://localhost/database?schema=database
# db.url=jdbc:h2:store001;AUTO_SERVER=TRUE;LOCK_TIMEOUT=60000
# The database user that SymmetricDS should use.
db.user=crm
# The database password
db.password=crm

# This node will contact the root node’s sync.url to register itself.
registration.url=http://10.111.111.191:31415/sync/source-000
sync.url=http://10.121.121.191:31415/sync/dest-001
# Node group this node belongs to, which defines what it will sync with who.
# Must match the sym_node_group configuration in database.
group.id=dest
# External ID for this node, which is any unique identifier you want to use.
external.id=001

# How to run routing (in millis), which puts changes into batches.
job.routing.period.time.ms=5000

# How often to run push (in millis), which sends changes to other nodes.
job.push.period.time.ms=10000

# How often to run pull (in millis), which receives changes from other nodes.
job.pull.period.time.ms=10000

On Production Source database

create the SymmetricDS-specific tables in the Production database. These tables will contain the configuration for synchronization. The following command uses the auto-creation feature to create all the necessary SymmetricDS system tables. thie command is required to be run only on production server.

cd /u04/symmetric-server-3.12.1/bin
./symadmin -engine source-000 create-sym-tables

Register target db from Source

./symadmin -engine source-000 open-registration dest 001

For initial load we are updating below tables update SYM_NODE_SECURITY set initial_load_enabled=1 where node_id=001;
update SYM_NODE set sync_enabled=1 where node_id=001;
commit;

Pr e-requiste table structure has to be there

Login to CRM01 user, create dummy table for replication
““““““““““““““““““““““““““`
sqlplus CRM01
create table TEST1 (a1 number, desc01 varchar2(100));
create table TEST2 (a1 number, desc01 varchar2(100));
create table TEST3 (a1 number, desc01 varchar2(100));
insert into TEST1 values(1,’das’);
insert into TEST1 values(2,’faheem’);
insert into TEST1 values(3,’shibin’);
insert into TEST2 values(2,’dev’);
insert into TEST3 values(3,’plato’);
commit;

symmetricds table configuration

The below script need to be executed for the data syncronization configuration between source to target. On target we will only create the table strucutre and initial load of data will happen to target once we start the service on source and target

insert into sym_node_group_link (source_node_group_id, target_node_group_id,data_event_action) values (‘source’, ‘dest’, ‘P’);
insert into sym_channel (channel_id, processing_order, max_batch_size,enabled, description) values(‘ho_sync_capricon’, 1, 100000, 1, ‘outbound channel’);
insert into sym_trigger (trigger_id, source_table_name, channel_id, last_update_time, create_time,sync_on_incoming_batch) values (‘outbound_tr_t1’, ‘TEST1′,’ho_sync_capricon’,sysdate,sysdate,1);
insert into sym_trigger (trigger_id, source_table_name, channel_id, last_update_time, create_time,sync_on_incoming_batch) values (‘outbound_tr_t2’, ‘TEST2′,’ho_sync_capricon’,sysdate,sysdate,1);
insert into sym_trigger (trigger_id, source_table_name, channel_id, last_update_time, create_time,sync_on_incoming_batch) values (‘outbound_tr_t3’, ‘TEST3′,’ho_sync_capricon’,sysdate,sysdate,1);
insert into sym_router (router_id,source_node_group_id,target_node_group_id,router_type,create_time,last_update_time) values(‘ho-capricon’, ‘source’, ‘dest’, ‘default’,current_timestamp, current_timestamp);
insert into sym_trigger_router (trigger_id,router_id,initial_load_order,last_update_time,create_time) values(‘outbound_tr_t1′,’ho-capricon’, 1, current_timestamp, current_timestamp);
insert into sym_trigger_router (trigger_id,router_id,initial_load_order,last_update_time,create_time) values(‘outbound_tr_t2′,’ho-capricon’, 1, current_timestamp, current_timestamp);
insert into sym_trigger_router (trigger_id,router_id,initial_load_order,last_update_time,create_time) values(‘outbound_tr_t3′,’ho-capricon’, 1, current_timestamp, current_timestamp);

On Target login to CRM user and create table structure for replication
sqlplus crm/crm
create table TEST1 (a1 number, desc01 varchar2(100));
create table TEST2 (a1 number, desc01 varchar2(100));
create table TEST3 (a1 number, desc01 varchar2(100));
commit;

START SYMMETRICDS

  • Source Start service and then on target from Oracle OS user
    cd /u04/symmetric-server-3.12.1/bin
    nohup ./sym > /u04/symmetric-server-3.12.1/sym.log 2>&1 &

    To monitor the symmetricds status you can tail the log file found on source location
    (/u04/symmetric-server-3.12.1/log)
    tail -f ../logs/symmetric.log
  • Target Start service and then on target from Oracle OS user
    cd /home/oracle/symds/symmetric-server-3.12.1/bin
    ./sym_service start
    tail -f ../logs/symmetric.log

    –on source check table sym_node updated with correct url

CHECK THE DATA SYNC STATUS

Query the tables login to CRM user on target and check table data has been replicated from source to target. Can insert some data on Source test tables and check the data getting replicated on Target

CREATE DB LINK FOR SYNC MAIL REPORTING
To monitor the status of sync between source and target we created a dblink on source.
CREATE DATABASE LINK xetrg CONNECT TO crm IDENTIFIED BY crm USING ‘XE’;

Create SQL FILE for monitoring the Data sync Status
We created scripts to monitor the database sync status for the replicated tables,
in our case test1, test2 and test3 tables. We will also configure cronjob to trigger
a mail on hourly basis to know the sync status

vi /home/oracle/scripts/rep_check.sql
SET SERVEROUTPUT Off
SET DEFINE OFF
set pagesize 100
set linesize 150
–set heading off
Set Newpage none
column Table_name format a30
column HO format 999999999999
column CRM_Trg format 999999999999
column Difference format 999999999999
spool /home/oracle/scripts/dailymonitordb.log
select ” from dual;
select ‘TEST1’ Table_name, (select count() from TEST1) HO, (select count() from TEST1@xetrg) CRM_Trg, (select count() from TEST1)-(select count() from TEST1@xetrg)Difference from dual union all
select ‘TEST2’ Table_name, (select count() from TEST2) HO, (select count() from TEST2@xetrg) CRM_Trg, (select count() from TEST2)-(select count() from TEST2@xetrg)Difference from dual union all
select ‘TEST2_PRV’ Table_name, (select count() from TEST2_PRV) HO, (select count() from TEST2_PRV@xetrg) CRM_Trg, (select count() from TEST2_PRV)-(select count() from TEST2_PRV@xetrg)Difference from dual;
select ” from dual;
exit

[oracle@MRCPRDBI-ORCL01 ~]$ cat /home/oracle/scripts/dailymonitordbdr.sh
cd /home/oracle/scripts/
export TMP=/tmp
export TMPDIR=$TMP
export ORACLE_HOSTNAME=MRCPRDBI-ORCL01
export ORACLE_UNQNAME=mrcprdb
export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=$ORACLE_BASE/product/12.1.0.2/db_1
export ORACLE_SID=mrcprdb
export PATH=/usr/sbin:/usr/local/bin:$PATH
export PATH=$ORACLE_HOME/bin:$PATH
export PATH=$ORACLE_HOME/OPatch:$PATH
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib
export CLASSPATH=$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib
echo “Below Replication Symetric status” >> dailymonitordb.log
sqlplus crm01/crm01 @/home/oracle/scripts/rep_check.sql
echo “” >> dailymonitordb.log
mail -s “MRCPRDBI Data sync monitoring” -v -r donotreply@MRCPRDBI.com oracleprolab@gmail.com < dailymonitordb.log
exit

[oracle@MRCPRDBI-ORCL01 ~]$ chmod 775 /home/oracle/scripts/dailymonitordbdr.sh
[oracle@MRCPRDBI-ORCL01 ~]$ chmod 775 /home/oracle/scripts/rep_check.sql

Schedule cronjob to run mail alert hourly
[oracle@MRCPRDBI-ORCL01 ~]$ crontab -l
0 * * * * /home/oracle/scripts/dailymonitordbdr.sh

Sample mail Alert

************************Below Replication Symetric status***************

‘Test1’ CRM01 XETRG DIFFERENCE
Test1 327183 327183 0
Test2 22297 22297 0
Test3 384438 384438 0

By mithun

2 thoughts on “Oracle Database data synchronization using SymmetricDS (Oracle EE – Oracle-XE Table data Replication)”

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.