Migrating an On-premises Database to the Cloud with Zero Downtime – Part 1

Oracle Cloud provides the best environment for Oracle Database deployment on cloud, There is no doubt about it. There are multiple options to deploy oracle databases on public or On-Premises Cloud. When it comes to Oracle cloud, some of the options:

  1. Oracle Database Cloud Service Bare Metal
  2. Oracle Database Cloud Service Virtual Machine
  3. Exadata Cloud Service
  4. Exadata Cloud at Customer

Oracle Cloud also support all the future of Oracle such as High Availability, Real Application Clusters, shards, Replication etc. Oracle also provide various tools to migration On-Premises database to Oracle cloud. One of the new tool Oracle introduced is the Zero downtime Migration tool (ZDM)

ZDM can be used to move Oracle on-premises database to a database system in the cloud with zero downtime. Oracle Zero Downtime Migration is Oracle’s preferred automated tool for migrating the same database type and version from on-premises to Oracle Cloud.

ZDM requires a Linux host Oracle Linux 7 or later. The Linux host where ZDM software will be installed should not have Oracle Grid Infrastructure Installed or running.

Download the Zero Downtime Migration (ZDM) software kit and install it on the Zero Downtime Migration service host. Install the Zero Downtime Migration software as a non-root user.

Installation is very simple, Create a zdm group and non-root user, zdmuser, on the ZDM service host. ZDM need linux libraries such as glib-devel, expect and libaio.

[root@snode1 ~]# groupadd zdm -g 1001
[root@snode1 ~]# useradd zdmuser -g 1001
Most probably, you have to install glibc-devel expect libaio
[root@snode1 zdm]# rpm -qa | egrep "glibc-devel|expect|libaio"

If they are not installed, use yum to install it.

yum install glibc-devel expect libaio

unzip the zdm zip file downloaded from oracle. I unzipped zdm file to /u02/app/oracle/zdm. After unzipping this directory will have a file called zdm_home.zip. For newer version, zdm_home.zip is under zdm19-7_ver2

[zdmuser@snode1 zdm_soft]$ unzip zdm19-7_ver2.zip
Archive:  zdm19-7_ver2.zip
   creating: zdm19-7_ver2/
  inflating: zdm19-7_ver2/README     
  inflating: zdm19-7_ver2/zdminstall.sh  
 extracting: zdm19-7_ver2/zdm_home.zip  
[zdmuser@snode1 zdm_soft]$ ls -ltr
total 3291492
drwxr-xr-x 2 zdmuser oinstall       4096 Dec 10 09:09 zdm19-7_ver2
-rwxr-xr-x 1 zdmuser zdm      3367187760 Feb  4 11:23 zdm19-7_ver2.zip

Like normal install, it is good idea to put it into it’s own home

mkdir -p /u02/app/oracle/zdm /u02/app/oracle/base

Then use zdminstall.sh setup to install zdm

[zdmuser@snode1 zdm19-7_ver2]$ ./zdminstall.sh setup oraclehome=/u02/app/oracle/zdm oraclebase=/u02/app/oracle/base   ziploc=/u02/app/oracle/zdm_soft/zdm19-7_ver2/zdm_home.zip -zdm
ZDM kit home: /u02/app/oracle/zdm_soft/zdm19-7_ver2
Unzipping shiphome to ZDM home...
Unzipping shiphome...
Shiphome unzipped successfully..
##### Starting GridHome Software Only Installation #####
Launching Oracle Grid Infrastructure Setup Wizard...
[WARNING] [INS-42505] The installer has detected that the Oracle Grid Infrastructure home software at (/u02/app/oracle/zdm) is not complete.
   CAUSE: Following files are missing:
[/u02/app/oracle/zdm/jlib/jackson-annotations.jar, /u02/app/oracle/zdm/jlib/jackson-core.jar, /u02/app/oracle/zdm/jlib/jackson-databind.jar, /u02/app/oracle/zdm/jlib/jackson-jaxrs-base.jar, /u02/app/oracle/zdm/jlib/jackson-jaxrs-json-provider.jar, /u02/app/oracle/zdm/jlib/jackson-module-jaxb-annotations.jar, /u02/app/oracle/zdm/jlib/jersey-client-2.24.jar, /u02/app/oracle/zdm/jlib/jersey-common-2.24.jar, /u02/app/oracle/zdm/jlib/jersey-container-servlet-2.24.jar, /u02/app/oracle/zdm/jlib/jersey-container-servlet-core-2.24.jar, /u02/app/oracle/zdm/jlib/jersey-entity-filtering-2.24.jar, /u02/app/oracle/zdm/jlib/jersey-guava-2.24.jar, /u02/app/oracle/zdm/jlib/jersey-media-jaxb-2.24.jar, /u02/app/oracle/zdm/jlib/jersey-media-json-jackson-2.24.jar, /u02/app/oracle/zdm/jlib/jersey-server-2.24.jar]
   ACTION: Ensure that the Oracle Grid Infrastructure home at (/u02/app/oracle/zdm) includes the files listed above.
[WARNING] [INS-41813] OSDBA for ASM, OSOPER for ASM, and OSASM are the same OS group.
   CAUSE: The group you selected for granting the OSDBA for ASM group for database access, and the OSOPER for ASM group for startup and shutdown of Oracle ASM, is the same group as the OSASM group, whose members have SYSASM privileges on Oracle ASM.
   ACTION: Choose different groups as the OSASM, OSDBA for ASM, and OSOPER for ASM groups.
[WARNING] [INS-41874] Oracle ASM Administrator (OSASM) Group specified is same as the inventory group.
   CAUSE: Operating system group oinstall specified for OSASM Group is same as the inventory group.
   ACTION: It is not recommended to have OSASM group same as inventory group. Select any of the group other than the inventory group to avoid incorrect configuration.
[WARNING] [INS-32020] Installer has detected that the available disk space on the volume for the specified Oracle base location (/u02/app/oracle/base) is less than the recommended value.
   ACTION: It is recommended that the volume for the Oracle base have at least 10 GB of available disk space. Choose a location that has sufficient available disk space or free up space on the existing volume.
[WARNING] [INS-30100] Insufficient disk space on the selected location (/u02/app/oracle/zdm).
   CAUSE: Specified location is on a volume without enough disk space on nodes: [snode1].
   ACTION: Choose a location that has enough space (minimum of 6.9 GB) or free up space on the existing volume.
Summary of node specific errors
[WARNING] [INS-13014] Target environment does not meet some optional requirements.
   CAUSE: Some of the optional prerequisites are not met. See logs for details. /u01/app/oraInventory/logs/GridSetupActions2021-02-04_11-49-37AM/gridSetupActions2021-02-04_11-49-37AM.log
   ACTION: Identify the list of failed prerequisite checks from the log: /u01/app/oraInventory/logs/GridSetupActions2021-02-04_11-49-37AM/gridSetupActions2021-02-04_11-49-37AM.log. Then either from the log file or from installation manual find the appropriate configuration to meet the prerequisites and fix it manually.
The response file for this session can be found at:
You can find the log of this install session at:
As a root user, execute the following script(s):
        1. /u02/app/oracle/zdm/root.sh
Execute /u02/app/oracle/zdm/root.sh on the following nodes: 
Successfully Setup Software with warning(s).
making dir /u02/app/oracle/base/crsdata/snode1/rhp/conf
Generating Preference file
Generating Root Certificate
Cluster root certificate generated successfully.
Generating CA CERTS file
spawn /u02/app/oracle/zdm/bin/crskeytoolctl -copycacerts -filestore /u02/app/oracle/base/crsdata/snode1/security/
Enter JRE cacerts truststore password: 
JRE cacerts copied to file [/u02/app/oracle/base/crsdata/snode1/security/cacerts].
Generating nogi.enabled file
nogi.enabled file generated sucessfully
Generating standalone_config.properties file
Setting base folder permissions
Copying service script to bin folder in Oracle Home
ZDM service setup finished successfully...

Please note that those WARNINGs can be ignored. If the installation is successful, we can try starting the services.

[zdmuser@snode1 zdm19-7_ver2]$ cd  /u02/app/oracle/zdm/bin
[zdmuser@snode1 bin]$ ./zdmservice start
No instance detected, starting zdmservice
[jwcctl debug] Environment ready to start JWC
[jwcctl debug] Return code of initialization: [0]
[jwcctl debug] ... BEGIN_DEBUG [Action= start] ...
Start JWC
[jwcctl debug] Loading configuration file: /u02/app/oracle/base/crsdata/snode1/rhp/conf/jwc.properties
[jwcctl debug]     oracle.jmx.login.credstore = CRSCRED
[jwcctl debug]     oracle.jmx.login.args = DOMAIN=rhp CACHE_ENABLED=true CACHE_EXPIRATION=180
[jwcctl debug]     oracle.rmi.url = service:jmx:rmi://{0}:{1,number,#}/jndi/rmi://{0}:{1,number,#}/jmxrmi
[jwcctl debug]     oracle.http.url = http://{0}:{1,number,#}/rhp/gridhome
[jwcctl debug]     oracle.jwc.tls.clientauth = false
[jwcctl debug]     oracle.jwc.tls.rmi.clientfactory = RELOADABLE
[jwcctl debug]     oracle.jwc.lifecycle.start.log.fileName = JWCStartEvent.log
[jwcctl debug] /u02/app/oracle/zdm/bin/jwcctl.pl: 42056 file opened
[jwcctl debug] /u02/app/oracle/zdm/bin/jwcctl.pl: 42056 acquired lock
Node rekey action ran successfully.
[jwcctl debug] /u02/app/oracle/zdm/bin/jwcctl.pl: 42056 released lock
[jwcctl debug] Get JWC PIDs
[jwcctl debug] Done Getting JWC PIDs
[jwcctl debug] ... JWC containers not found ...
[jwcctl debug]     Start command:-server -Xms2048M -Xmx4096M -Djava.awt.headless=true -Ddisable.checkForUpdate=true -Djava.util.logging.config.file=/u02/app/oracle/base/crsdata/snode1/rhp/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -DTRACING.ENABLED=true -DTRACING.LEVEL=2 -Doracle.wlm.dbwlmlogger.logging.level=FINEST -Duse_scan_IP=true -Djava.rmi.server.hostname=snode1 -Doracle.http.port=8896 -Doracle.jmx.port=8895 -Doracle.tls.enabled=false -Doracle.jwc.tls.http.enabled=true -Doracle.rhp.storagebase=/u02/app/oracle/base -Djava.security.egd=file:/dev/./urandom -Doracle.jwc.wallet.path=/u02/app/oracle/base/crsdata/snode1/security -Doracle.jmx.login.credstore=WALLET -Dcatalina.home=/u02/app/oracle/zdm/tomcat -Dcatalina.base=/u02/app/oracle/base/crsdata/snode1/rhp -Djava.io.tmpdir=/u02/app/oracle/base/crsdata/snode1/rhp/temp -Doracle.home=/u02/app/oracle/zdm -Doracle.jwc.mode=STANDALONE -classpath /u02/app/oracle/zdm/jlib/cryptoj.jar:/u02/app/oracle/zdm/jlib/oraclepki.jar:/u02/app/oracle/zdm/jlib/osdt_core.jar:/u02/app/oracle/zdm/jlib/osdt_cert.jar:/u02/app/oracle/zdm/tomcat/lib/tomcat-juli.jar:/u02/app/oracle/zdm/tomcat/lib/bootstrap.jar:/u02/app/oracle/zdm/jlib/jwc-logging.jar org.apache.catalina.startup.Bootstrap start
[jwcctl debug] Get JWC PIDs
[jwcctl debug] Done Getting JWC PIDs
[jwcctl debug] ... JWC Container (pid=42195) ...
[jwcctl debug] ... JWC Container running (pid=42195) ...
[jwcctl debug]     Check command:-Djava.net.preferIPv6Addresses=true -Dcatalina.base=/u02/app/oracle/base/crsdata/snode1/rhp -Doracle.wlm.dbwlmlogger.logging.level=FINEST -Doracle.jwc.client.logger.file.name=/u02/app/oracle/base/crsdata/snode1/rhp/logs/jwc_checker_stdout_err_%g.log -Doracle.jwc.client.logger.file.number=10 -Doracle.jwc.client.logger.file.size=1048576 -Doracle.jwc.wallet.path=/u02/app/oracle/base/crsdata/snode1/security -Doracle.jmx.login.credstore=WALLET -Doracle.tls.enabled=false -Doracle.jwc.tls.http.enabled=true -classpath /u02/app/oracle/zdm/jlib/jwc-logging.jar:/u02/app/oracle/zdm/jlib/jwc-security.jar:/u02/app/oracle/zdm/jlib/jwc-client.jar:/u02/app/oracle/zdm/jlib/jwc-cred.jar:/u02/app/oracle/zdm/jlib/srvm.jar:/u02/app/oracle/zdm/jlib/srvmhas.jar:/u02/app/oracle/zdm/jlib/cryptoj.jar:/u02/app/oracle/zdm/jlib/oraclepki.jar:/u02/app/oracle/zdm/jlib/osdt_core.jar:/u02/app/oracle/zdm/jlib/osdt_cert.jar:/u02/app/oracle/zdm/tomcat/lib/tomcat-juli.jar oracle.cluster.jwc.tomcat.client.JWCChecker localhost 8896 -1
[jwcctl debug] ... JWC Container is ready ...
[jwcctl debug] ... START - Return code = 0 ...
[jwcctl debug]  ... END_DEBUG [Action=start] ...
[jwcctl debug] Return code of AGENT: [0]
Return code is 0
Server started successfully.
[zdmuser@snode1 bin]$ ./zdmservice status
        Service Status
 Running:       true
 Conn String:   jdbc:derby:/u02/app/oracle/base/derbyRepo;create=true
 Repo Path:     /u02/app/oracle/base/derbyRepo
 RMI port:      8895
 HTTP port:     8896
 Wallet path:   /u02/app/oracle/base/crsdata/snode1/security
[zdmuser@snode1 bin]$ ./zdmcli query image
snode1.localdomain: Audit ID: 2
No image has been configured

In the next article we will do a migration of Oracle database from On-Premises to OCI