Until recently, most organizations I work with have been comfortable running their databases and applications across two regions. Sometimes that is an Active/Standby configuration, but more often I see some form of Active/Active. The big change I have seen recently is the addition of a third site, often described as a "cyber vault" or an IRE (Isolated Recovery Environment).
To provide that third site, many customers are looking at hosting a standby database in the cloud, either in OCI or through Oracle Database@ services in a multicloud environment. A practical way to limit traffic from the on-premises environment is to only send redo to the cloud database with Data Guard, then back up that cloud database to Autonomous Recovery Service. The backup workload stays on the cloud side.
Creating a cloud standby from your on-premises database is easier than you might think. In this post, I go through the standby build and the next step: configuring backups to Autonomous Recovery Service.
One thing to keep in mind is that a standby database and backups are only part of the picture. To use this as a cyber vault or IRE, you also need to control who can access it and which systems can connect to it. You need to protect the encryption keys and test that you can restore the database to a point before an attack or data corruption occurred. Plan for all of this as you build the standby and configure the backups..
The third-site pattern: send redo to a cloud standby, then back up the standby to Autonomous Recovery Service. The worked example below uses Oracle Exadata Database Service in OCI.
I recently went through the Oracle documentation for creating a hybrid Data Guard configuration. There is a lot of information to work through, especially when you are trying to figure out what needs to be ready before you start.
I am breaking this into four parts:
- Get the prerequisites in place.
- Run
dbcactlto prepare the primary database. - Run
dbaasclito create the standby database in OCI. - Configure backups from the cloud standby to Autonomous Recovery Service.
Once the preparation is done, the standby build comes down to two commands. I will go through their parameters and what dbcactl and dbaascli are doing, then show where Recovery Service fits into the third-site design.
For this walkthrough, I am showing an on-premises Oracle RAC primary with a standby on Oracle Exadata Database Service in OCI. I have changed the database names and hostnames to use a generic sales example. My example build used a 19c Oracle Home and DBAAS CLI 26.3.1.0.0.
NOTE: The cloud VM cluster and Oracle Home need to exist before you start. configureStandby creates the database within that cluster. Refer to the full Oracle guide for platform requirements and configurations with additional standbys.
1 What needs to be ready before I start
First, let's go through the pieces that need to be in place before running either command.
- Download
dbcactl. My Oracle Support document 3099785.1, linked from the hybrid guide, has the download and installation instructions. I am using/home/oracle/dbcacl/dbcactlin the example. The folder is nameddbcacl, and the executable isdbcactl. - Have the cloud Oracle Home ready. Match the primary release, RU, and one-off patches where possible. If you need a different RU, check the combinations allowed in the guide.
- Check connectivity in both directions. The primary needs to reach the cloud, and the cloud needs to reach the primary. Check DNS, SSH, and Oracle Net for all RAC nodes and SCAN endpoints. The network also needs enough bandwidth for the initial copy and ongoing redo.
- Have a shared ACFS directory on the primary. This is where the network files and wallet configuration can be shared between instances. For this example I am using
/acfs01/saleson an existing mounted ACFS filesystem. - Prepare the primary for Data Guard. This includes standby redo logs, logging, Flashback Database, Oracle Net encryption, and enough recovery-area space. Follow the MAA recommendations in the guide.
Make sure the encryption keys are there
One thing I want to call out is the TDE wallet. Even if the on-premises primary is not encrypted, it still needs a wallet with master encryption keys for this hybrid configuration. The cloud database needs those keys.
For this example I am using a file-based TDE keystore. Before starting, I would check that the wallet is usable and that the keys exist in the CDB root and each PDB other than the seed. The TDE with Data Guard documentation goes through the key handling.
For 19c at RU 19.16 or later, these are the settings I would look at:
| Parameter | Example or policy | Purpose |
|---|---|---|
WALLET_ROOT | /acfs01/sales/wallet | Root directory for wallet storage; the file-based TDE wallet is under tde. Use your existing keystore location. |
TDE_CONFIGURATION | KEYSTORE_CONFIGURATION=FILE | Selects the file-based keystore used in this example. |
TABLESPACE_ENCRYPTION | Choose for each site | AUTO_ENABLE is the cloud policy. DECRYPT_ONLY is an on-premises option when encrypted tablespaces must be avoided. Do not apply it to the cloud standby. |
NOTE: Setting the parameters does not create the wallet or set the master keys. Also, WALLET_ROOT is static, so changing it requires a restart.
If you still need to set up the wallet, follow the TDE configuration procedure. The TABLESPACE_ENCRYPTION reference explains the encryption policies. For earlier RUs, use the release-specific settings in the hybrid guide.
Here is a quick check I can run on the primary, connected through SQL*Plus as oracle:
SELECT name, db_unique_name, database_role, log_mode,
force_logging, flashback_on
FROM v$database;
SHOW PARAMETER wallet_root
SHOW PARAMETER tde_configuration
SHOW PARAMETER tablespace_encryption
SELECT con_id, status, wallet_type, wrl_parameter
FROM v$encryption_wallet;
I want the primary in ARCHIVELOG mode, with force logging enabled and Flashback Database prepared before moving on. If archive logging still needs to be enabled, plan for the maintenance window that change may require.
I would also check V$DATABASE_KEY_INFO and V$ENCRYPTION_KEYS in the root and relevant PDBs. An open wallet is only part of the check; I need the master keys as well. If the wallet shows OPEN_NO_MASTER_KEY, that needs to be addressed before the build.
Use your existing key-management procedure and wallet location. There is no reason to replace an existing wallet just to match the path in my example.
Finally, have the primary SYS password, the TDE wallet password, and the password you will supply for AWR administration ready. These have different purposes and do not need to be the same.
Get Recovery Service ready as well
For the backup step, I also need the Recovery Service IAM policies, network connectivity, and a registered Recovery Service subnet. For 19c, the documented minimum is RU 19.18. Broker is mandatory for this backup destination in a Data Guard configuration with dbaascli 25.3.1.0.0 and later. I would also check regional availability, service limits, and the retention policy I need. The Exadata backup guide covers these prerequisites.
The names I am using in the example
| Item | Generic value |
|---|---|
| Database name on both sites | sales |
| Primary database unique name | sales_primary |
| Standby database unique name | sales_stby |
| Primary SCAN | onprem-scan.example.com |
| Standby SCAN | cloud-scan.example.com |
| Primary database service | sales_primary.example.com |
| SCAN listener port on both sites | 1521 |
| Existing cloud Oracle Home | /u02/app/oracle/product/19.0.0.0/dbhome_1 |
You can see that I am using sales as the database name on both sides. The unique names are different: sales_primary and sales_stby.
The other distinction to keep in mind is the SCAN name versus the database service. The SCAN gets me to the cluster, and the service identifies the database connection. Use the actual service registered with your primary listener when replacing sales_primary.example.com.
2 Run dbcactl on the primary

Figure 1. Run the preparation command on the first primary node. The standby SCAN already belongs to the provisioned cloud cluster.
Now I can prepare the primary. The diagram above shows the database and its SCAN listener, along with the cloud SCAN I will pass to the command.
I run this as oracle on the first primary node, with ORACLE_HOME and the local ORACLE_SID set for the source database. The shared directory /acfs01/sales also needs to be writable by oracle.
Here is the command with the example names:
/home/oracle/dbcacl/dbcactl \
-silent \
-oui_internal \
-configureDatabase \
-prepareForStandby \
-dgTNSNamesoraFilePath /acfs01/sales \
-sourceDB sales_primary \
-gdbName sales.example.com \
-standbyDBUniqueName sales_stby \
-standbyScanName cloud-scan.example.com \
-standbyScanPort 1521 \
-primaryScanPort 1521 \
-pdbServiceDomain example.com \
-blobFileLocation /tmp
The command prompts for the primary SYS password. In my run, I could see it creating the Data Guard services, updating tnsnames.ora and the include-file entry, and then preparing the standby bundle.
What the dbcactl parameters mean
| Parameter | Value in this example | Meaning |
|---|---|---|
-silent | Flag | Runs without the graphical assistant; password prompts still appear. |
-oui_internal | Flag | Workflow flag that allows for the use of prepareForStandby (which is a hidden parameter) |
-configureDatabase | Flag | Selects database configuration. |
-prepareForStandby | Flag | Selects primary preparation for a standby. |
-dgTNSNamesoraFilePath | /acfs01/sales | Directory for the Data Guard network configuration. |
-sourceDB | sales_primary | Identifies the primary by its unique name. |
-gdbName | sales.example.com | Global database name passed to the workflow. |
-standbyDBUniqueName | sales_stby | Unique name planned for the standby. |
-standbyScanName | cloud-scan.example.com | SCAN hostname for the existing standby cluster. |
-standbyScanPort | 1521 | Standby SCAN listener port. |
-primaryScanPort | 1521 | Primary SCAN listener port. |
-pdbServiceDomain | example.com | PDB service domain passed to the workflow. |
-blobFileLocation | /tmp | Output directory for the generated bundle. |
These are the options from my successful command, with the environment names changed. If you are using a different utility version, check its supported options, especially -gdbName and -pdbServiceDomain.
NOTE: My original run included -skipFlashbackValidation and -skipForceLoggingValidation. I have left those out here so the checks run. Skipping a check does not remove the need to prepare the database.
At the end, the command tells me where it wrote the .tar file. The filename will look like this, with a generated timestamp and ID:
Successfully created blob file:
/tmp/sales_<generated_timestamp>_<generated_id>.tar
This file contains the preparation material, including network files and the TDE wallet. I need to copy it securely to the first cloud node before running the second command.
For example, I can use scp:
scp /tmp/sales_<generated_timestamp>_<generated_id>.tar opc@cloud-node1.example.com:/tmp/
Replace the timestamp and ID with the actual filename from your output. For the next command, I am using /tmp/sales_standby.tar as a simpler name for the transferred file. You can keep the generated name instead; just use the same path in --standbyBlobFromPrimary.
NOTE: The bundle contains wallet material. Keep access to it restricted during the transfer and on the destination.
3 Run dbaascli to create the standby

Figure 2. The existing cloud VM cluster hosts the new standby database. The primary and standby share DB_NAME=sales and have different unique names.
Now that the bundle is on the cloud node, I can create the standby database.
This command runs as root on the first cloud node. The Oracle Home in the command is the existing cloud home where the standby will be created.
dbaascli dataguard configureStandby \
--activeDG true \
--standbyDBUniqueName sales_stby \
--standbyScanIPAddresses cloud-scan.example.com \
--protectionMode MAX_PERFORMANCE \
--standbyScanPort 1521 \
--dbname sales \
--oracleHome /u02/app/oracle/product/19.0.0.0/dbhome_1 \
--primaryScanIPAddresses onprem-scan.example.com \
--primaryServiceName sales_primary.example.com \
--transportType ASYNC \
--primaryScanPort 1521 \
--standbyBlobFromPrimary /tmp/sales_standby.tar \
--noDBDomain
What the dbaascli parameters mean
| Parameter | Value in this example | Meaning |
|---|---|---|
--activeDG | true | Requests Active Data Guard. Use an appropriate service entitlement for read-only access while apply runs. |
--standbyDBUniqueName | sales_stby | Standby unique name. |
--standbyScanIPAddresses | cloud-scan.example.com | Standby SCAN name or comma-separated SCAN IPs. |
--protectionMode | MAX_PERFORMANCE | Data Guard protection mode. |
--standbyScanPort | 1521 | Standby listener port. |
--dbname | sales | Database name. |
--oracleHome | /u02/app/oracle/product/19.0.0.0/dbhome_1 | Existing target Oracle Home. |
--primaryScanIPAddresses | onprem-scan.example.com | Primary SCAN name or comma-separated SCAN IPs. |
--primaryServiceName | sales_primary.example.com | Primary database service. |
--transportType | ASYNC | Redo transport mode. |
--primaryScanPort | 1521 | Primary listener port. |
--standbyBlobFromPrimary | /tmp/sales_standby.tar | Transferred preparation bundle. |
--noDBDomain | Flag | Omits the standby database domain. |
You may have noticed that I passed SCAN hostnames to parameters named IPAddresses. These parameters accept either a SCAN name or a comma-separated list of SCAN IP addresses. You can find the options in the dbaascli command reference.
I am also using --noDBDomain for the standby. That controls the database domain, so the SCAN and primary service can still have fully qualified names. If you need a standby database domain, use --standbyDBDomain and make sure it agrees with the preparation settings.
The command asks for the following passwords:
Enter PRIMARY_DB_SYS_PASSWORD:
Enter PRIMARY_DB_TDE_PASSWORD:
Enter AWR_ADMIN_PASSWORD:
Enter AWR_ADMIN_PASSWORD (reconfirmation):
What is happening while dbaascli runs
This is the part I wanted to spend a little time on. There is a lot of output from dbaascli, and it helps to understand what all those jobs are doing.
Looking through my output, I can group the work into five pieces:
- Validate the target. Check the inputs, VM type, Oracle Home version, Clusterware, database names, disk space, memory, TDE configuration, and storage compatibility.
- Prepare the databases. Fetch the bundle, prepare primary configuration, enable primary logging, configure primary flashback, generate standby metadata, and configure the standby database. These jobs can change the primary as well as the target.
- Configure connectivity and encryption. Update
sqlnet.ora,tnsnames.ora, listener parameters, and the standby wallet. - Integrate Data Guard and cloud management. Configure redo routing, verify Broker status, and update cloud automation and database registry metadata.
- Configure AWR integration and finish. Configure AWR accounts, links, node registration, and a remote snapshot; generate database and Data Guard details; then clean up.
One thing to keep in mind is that copying the bundle is only the handoff between the two commands. The database data still needs to be copied to create the standby. The hybrid guide describes the RMAN channels used during that part of the build.
How long it takes will depend on the database size, the source workload, the cloud resources, and the network between the two environments.
My run finished with:
dbaascli execution completed
Check the standby after the build
The next thing I would do is check the database and Data Guard configuration. Keep the session log path that dbaascli prints; it is useful if you need to go back through the build.
As root on the cloud node, I can run:
dbaascli database getDetails --dbname sales
dbaascli dataguard getDetails --dbName sales
I want to see the physical standby role, a successful configuration status, and redo transport enabled on the primary.
Then, as oracle with the standby environment set, I would check Broker:
dgmgrl / 'show configuration'
dgmgrl / 'show database verbose sales_stby'
dgmgrl / 'validate database sales_stby'
Here I would look at transport lag, apply lag, the recovery state, and any Broker warnings. Since I requested Active Data Guard, I would also check that the standby is open read-only with apply running.
The completed build is a good starting point. Before relying on it for disaster recovery, I still want to validate the configuration, check the lag, and test the role transitions.
4 Back up the cloud standby to Autonomous Recovery Service
Now I have the database at the third site. The next step is to give it a recovery history. Data Guard keeps the standby current; the backups give me earlier recovery points to work with if a problem has already reached that standby.
For an ExaDB-D standby exposed through a supported OCI Data Guard association, Oracle documents this console workflow in its standby backup and restore tutorial:
- Open the cloud standby's database details page. Confirm I am working with
sales_stby. - Choose Enable automatic backups and select Autonomous Recovery Service as the destination.
- Set the retention policy and backup schedule, then save the configuration.
- Check the backup details and confirm a successful backup. The tutorial also shows creating a database from a standby backup, which is a useful recovery test.
NOTE: The hybrid command does not configure Recovery Service backups. If the console does not expose the backup action for the CLI-created hybrid database, confirm the supported backup configuration procedure for that deployment before continuing. Check the corresponding service guidance for Database@ deployments as well.
DO NOT configure Real-time redo when configuring the Autonomous Recovery service. Real-time redo requires creating a user in the primary database which out of the control of the tooling.
Backup settings can be fine tuned and these settings are described in the Exadata backup guide.
Test the third-site recovery process
My final check is a recovery exercise: choose a recovery point, restore into the intended recovery environment, verify the keys are available, and validate the database and application data.

No comments:
Post a Comment