{"id":1002,"date":"2025-05-24T16:16:40","date_gmt":"2025-05-24T14:16:40","guid":{"rendered":"https:\/\/anjo.pt\/keyword-oracle\/?p=1002"},"modified":"2025-05-25T11:42:46","modified_gmt":"2025-05-25T09:42:46","slug":"configuring-hybrid-dataguard-and-have-standby-on-the-without-the-need-of-advanced-security-license","status":"publish","type":"post","link":"https:\/\/anjo.pt\/keyword-oracle\/2025\/05\/24\/configuring-hybrid-dataguard-and-have-standby-on-the-without-the-need-of-advanced-security-license\/","title":{"rendered":"Configuring Hybrid Dataguard and have standby on OCI without the need of advanced security license"},"content":{"rendered":"\n<p>Hybrid Dataguard is a relatively new 19c feature that allows to have one side of a Dataguard configuration not encrypted. This is particularly useful when having a primary on premises and standby on a OCI, where tablespaces need to be encrypted. The main point is that it allows to spare a Advanced Security licenses on premises site. <\/p>\n\n\n\n<p>Usages of Hybrid Dataguard can be during migration to the cloud or just as a high availability solution, when we have a small on-premises data center. <\/p>\n\n\n\n<p>In the tutorial below I assume to have a primary database on premises without TDE, a we will create a standby in OCI with encryption enabled. The connection between on-premises and OCI is already configured and not explained.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">Pre-requisites<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Check that sqlnet port  (1521 or other) is open on both directions<\/li>\n\n\n\n<li>Make sure you can copy files between the servers (using ssh or other method).<\/li>\n<\/ul>\n\n\n\n<p>I use the following code to test if ports are open.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nIPLIST=&quot;10.161.97.224 10.161.97.225&quot;   # Destination IPs space separated\nfor IP in $IPLIST; do\n  for PORT in 22 1521; do\n    CHECK_IP=${IP}\/${PORT}\n    timeout 1 bash -c &quot;&amp;lt;\/dev\/tcp\/${CHECK_IP} &amp;amp;&amp;amp; echo Port ${CHECK_IP} is open || echo Port ${CHECK_IP} is closed&quot; || echo Connection timeout\n  done\ndone\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Prepare primary database<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Configure TDE Wallet <\/h3>\n\n\n\n<p>Even if the primary DB will not be encrypted, it is necessary to configure a TDE Wallet (called also Keystore). This requires a DB restart.<\/p>\n\n\n\n<p>First we create the wallet directory and set some static parameters.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nmkdir -p $ORACLE_BASE\/admin\/$ORACLE_SID\/wallet\/tde\nsqlplus \/ as sysdba\nSQL&gt; ALTER SYSTEM SET tablespace_encryption=DECRYPT_ONLY SCOPE=spfile;\nSQL&gt; ALTER SYSTEM SET wallet_root=&#039;\/u01\/app\/oracle\/admin\/cdb2\/wallet&#039; SCOPE=spfile;\n<\/pre><\/div>\n\n\n<p>Plan and <strong>restart database<\/strong> to activate the parameters.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nSQL&gt; shutdown immediate\nSQL&gt; startup\n<\/pre><\/div>\n\n\n<p>Then we define the TDE type as a software wallet (file), create the wallet and set a key for all containers (PDBs)<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nSQL&gt; ALTER SYSTEM SET tde_configuration=&#039;keystore_configuration=FILE&#039;;\nSQL&gt; ADMINISTER KEY MANAGEMENT CREATE KEYSTORE IDENTIFIED BY &quot;&lt;wallet password&gt;&quot;;\nSQL&gt; ADMINISTER KEY MANAGEMENT SET KEYSTORE OPEN IDENTIFIED BY &quot;&lt;wallet password&gt;&quot; container=all;\nSQL&gt; ADMINISTER KEY MANAGEMENT SET KEY IDENTIFIED BY &quot;&lt;wallet password&gt;&quot; with backup container=all;\nSQL&gt; COL wrl_parameter FOR a40\nSQL&gt; SELECT con_id,wrl_parameter, wrl_type, wallet_type, status from v$encryption_wallet;\n\n    CON_ID WRL_PARAMETER                            WRL_TYPE             WALLET_TYPE          STATUS\n---------- ---------------------------------------- -------------------- -------------------- ------------------------------\n         1 \/u01\/app\/oracle\/admin\/cdb2\/wallet\/tde\/         FILE                 PASSWORD             OPEN\n         2                                          FILE                 PASSWORD             OPEN\n         3                                          FILE                 PASSWORD             OPEN\n<\/pre><\/div>\n\n\n<p>Create an auto-login wallet, so the wallet opens automatically in read-only mode on DB startup. We close the read-write wallet, which is then automatically open in read-only mode (autologin).<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSQL&gt; ADMINISTER KEY MANAGEMENT CREATE AUTO_LOGIN KEYSTORE FROM KEYSTORE &#039;\/u01\/app\/oracle\/admin\/cdb2\/wallet\/tde\/&#039; IDENTIFIED BY &quot;&amp;lt;wallet password&gt;&quot;;\nSQL&gt; ADMINISTER KEY MANAGEMENT SET KEYSTORE CLOSE IDENTIFIED BY &quot;&amp;lt;wallet password&gt;&quot; container=all;\nSQL&gt; select con_id,WRL_PARAMETER, WRL_TYPE,WALLET_TYPE, status from V$ENCRYPTION_WALLET;\n    CON_ID WRL_PARAMETER                            WRL_TYPE             WALLET_TYPE          STATUS\n---------- ---------------------------------------- -------------------- -------------------- ------------------------------\n         1 \/u01\/app\/oracle\/admin\/cdb2\/wallet\/tde\/         FILE                 AUTOLOGIN            OPEN\n         2                                          FILE                 AUTOLOGIN            OPEN\n         3                                          FILE                 AUTOLOGIN            OPEN\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Pause database backups<\/h3>\n\n\n\n<p>Make sure that archivelogs generated during the creation of the standby are available until the end of the standby recovery.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Standby logs and parameter<\/h3>\n\n\n\n<p>We set automatic file management and create the standby logs. The loop below works well with up to 9 redologs per thread.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSQL&gt; alter system set STANDBY_FILE_MANAGEMENT=AUTO;\n\nSQL&gt; begin\nfor log_cur in ( select group#, thread#, bytes from v$log )\nloop\nexecute immediate &#039;alter database add standby logfile thread &#039; || log_cur.thread# || &#039; group &#039; || log_cur.thread# || &#039;0&#039; || log_cur.group# || &#039; size &#039; || log_cur.bytes ;\nend loop;\nend;\n\/\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Create dummy DB in OCI<\/h2>\n\n\n\n<p>We need to create a dummy DB in OCI with the same DB_NAME and different DB_UNIQUE_NAME from our primary DB. This is make so that it appears correctly in the portal. This dummy DB will be replaced by our standby. SYS and TDE passwords given are not relevant, as we will be using the ones from primary.<\/p>\n\n\n\n<p>I do the operation directly on the OCI VM Cluster.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nDBNAME=cdb2\nSTANDBY_UNQNAME=cdb2_oci\nSTANDBY_OH=\/u02\/app\/oracle\/product\/19.0.0.0\/dbhome_1\nPDB_NAME=DUMMY_PDB\n\ndbaascli database create \\\n--dbName $DBNAME \\\n--dbUniqueName $STANDBY_UNQNAME \\\n--oracleHome STANDBY_OH \\\n--pdbName $PDB_NAME \\\n--sgaSizeInMB 7600 \\\n--pgaSizeInMB 3072 \\\n--dbTerritory SWITZERLAND \\\n--dbCharset AL32UTF8 \\\n--dbNCharset AL16UTF16 \\\n--dbLanguage AMERICAN\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Create encrypted standby in OCI<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Copy Password file<\/h3>\n\n\n\n<p>Copy password file from on-premises to OCI<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nPRIMARY_HOST=vm1.anjo.ch\nDBNAME=cdb2\nLEGACY_OH=\/u01\/app\/oracle\/product\/19.24.0\/db_1\nscp $PRIMARY_HOST:$LEGACY_OH\/dbs\/orapw${DBNAME} \/tmp\/orapw${DBNAME}\n<\/pre><\/div>\n\n\n<p>Move the password files to ASM<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nsudo su - grid\n&#x5B;grid@oci-vm01 ~]$ \nDBNAME=cdb2\nSTANDBY_UNQNAME=CDB2_OCI\nDG_NAME=+DATAC1\n\nasmcmd pwcopy \/tmp\/orapw${DBNAME} \n${DG_NAME}\/${STANDBY_UNQNAME}\/PASSWORD\/orapw${STANDBY_UNQNAME}\n\nsudo su - oracle\n&#x5B;oracle@oci-vm1 ~]$ \nDBNAME=cdb2\nSTANDBY_UNQNAME=CDB2_OCI\nDG_NAME=+DATAC1\n\nsrvctl modify database -db ${STANDBY_UNQNAME} -pwfile ${DG_NAME}\/${STANDBY_UNQNAME}\/PASSWORD\/orapw${STANDBY_UNQNAME}\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Copy TDE Wallet<\/h3>\n\n\n\n<p>First check where in OCI is the wallet of the dummy configured. We will overwrite this wallet.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nsqlplus -S \/ as sysdba &amp;lt;&amp;lt;EOF\nshow parameter wallet_root\nEOF\n\nNAME                                 TYPE        VALUE\n------------------------------------ ----------- ------------------------------\nwallet_root                          string      \/var\/opt\/oracle\/dbaas_acfs\/cdb2\/wallet_root\n<\/pre><\/div>\n\n\n<p>And we copy the wallet from legacy to this location<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nDBNAME=cdb2\nscp $PRIMARY_HOST:\/u01\/app\/oracle\/admin\/${DBNAME}\/wallet\/tde\/*wallet* \/var\/opt\/oracle\/dbaas_acfs\/${DBNAME}\/wallet_root\/tde\/\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Restore control file<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;oracle@oci-vm1]$ rman target \/\nRMAN&gt; STARTUP NOMOUNT\nRMAN&gt; RESTORE STANDBY CONTROLFILE FROM SERVICE &#039;\/\/vm1.anjo.ch:1521\/cdb2.anjo.ch&#039;;\nRMAN&gt; ALTER DATABASE MOUNT;\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Restore as encrypted<\/h3>\n\n\n\n<p>We we use the new feature RESTORE AS ENCRYPTED DATABASE, which encrypts the datafiles while copying them from primary.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;oracle@oci-vm1]$ rman target \/ | tee \/home\/oracle\/duplicate_$(date &quot;+%Y_%m_%d-%Hh%M&quot;).log\nRMAN&gt; CONFIGURE DEVICE TYPE DISK PARALLELISM 4; \nRMAN&gt; RESTORE AS ENCRYPTED DATABASE FROM SERVICE &#039;\/\/vm1.anjo.ch:1521\/cdb2.anjo.ch&#039;;\nRMAN&gt; SWITCH DATABASE TO COPY;\n\nRMAN&gt; RECOVER DATABASE FROM SERVICE &#039;\/\/vm1.anjo.ch:1521\/cdb2.anjo.ch&#039;;\n<\/pre><\/div>\n\n\n<p>If DB is very large, one can then use recover to roll forward the standby without using archivelogs.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nsrvctl stop database -db ${STANDBY_UNQNAME}\nrman target \/\nRMAN&gt; STARTUP NOMOUNT\nRMAN&gt; RESTORE STANDBY CONTROLFILE FROM SERVICE &#039;\/\/vm1.anjo.ch:1521\/cdb2.anjo.ch&#039;;\nRMAN&gt; ALTER DATABASE MOUNT;\nRMAN&gt; CATALOG START WITH &#039;+DATAC1&#039; noprompt;   \/* ignore errors *\/\nRMAN&gt; CATALOG START WITH &#039;+RECOC1&#039; noprompt;  \/* ignore errors *\/\nRMAN&gt; SWITCH DATABASE TO COPY;\nRMAN&gt; SHUTDOWN IMMEDIATE;\n\nsrvctl start database -db ${STANDBY_UNQNAME} -startoption MOUNT\n\nrman target sys\/&amp;lt;password&gt;    # &amp;lt;-- It is necessary to provide password\nRMAN&gt; CONFIGURE DEVICE TYPE DISK PARALLELISM 4; \nRMAN&gt; RECOVER DATABASE FROM SERVICE &#039;\/\/vm1.anjo.ch:1521\/cdb2.anjo.ch&#039;;\nRMAN&gt; SWITCH DATABASE TO COPY;\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Set role as standby<\/h3>\n\n\n\n<p>The database should be set in the OCI clusterware as physical standby<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;oracle@oci-vm1]$ srvctl modify database -db ${STANDBY_UNQNAME} -role physical_standby -startoption mount\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Clear redologs <\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nbegin\nfor log_cur in ( select group# group_no from v$log )\nloop\nexecute immediate &#039;alter database clear logfile group &#039;||log_cur.group_no;\nend loop;\nend;\n\/\n\nbegin\nfor log_cur in ( select group# group_no from v$standby_log )\nloop\nexecute immediate &#039;alter database clear logfile group &#039;||log_cur.group_no;\nend loop;\nend;\n\/\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Prepare dataguard broker<\/h3>\n\n\n\n<p>First we prepare the broke in standby database<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nconnect \/ as sysdba\nSQL&gt; alter system set dg_broker_config_file1=&#039;+DATAC1\/&amp;lt;standby unique name&gt;\/dr1.dat&#039;;\nSQL&gt; alter system set dg_broker_config_file2=&#039;+RECOC1\/&amp;lt;standby unique name&gt;\/dr2.dat&#039;;\nSQL&gt; alter system set dg_broker_start=true;\nSQL&gt; alter system register;\n<\/pre><\/div>\n\n\n<p>Then we prepare on primary, connecting to it from OCI<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nconnect sys\/&amp;lt;password&gt;@&amp;lt;primary unique name&gt; as sysdba\nSQL&gt; alter system set dg_broker_config_file1=&#039;+DATAC1\/&amp;lt;standby unique name&gt;\/dr1.dat&#039;;\nSQL&gt; alter system set dg_broker_config_file2=&#039;+RECOC1\/&amp;lt;standby unique name&gt;\/dr2.dat&#039;;\nSQL&gt; alter system set dg_broker_start=true;\n<\/pre><\/div>\n\n\n<p>And create the dataguard configuration<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ndgmgrl sys\/&amp;lt;password&gt;@\/\/vm1.anjo.ch:1521\/cdb2.anjo.ch \nDGMGRL&gt; CREATE CONFIGURATION dgconfig AS PRIMARY DATABASE IS &amp;lt;primary unique name&gt; CONNECT IDENTIFIER IS &amp;lt;primary unique name&gt;;\nDGMGRL&gt; ADD DATABASE &amp;lt;standby unique name&gt; AS CONNECT IDENTIFIER IS &amp;lt;standby unique name&gt;;\nDGMGRL&gt; ENABLE CONFIGURATION;\nDGMGRL&gt; SHOW CONFIGURATION;\n<\/pre><\/div>\n\n\n<p>It might take a while until it shows &#8220;SUCCESSFUL&#8221;, important is to check in alertlog that the recovery is happening.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Post-operations<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Check if datafiles are encrypted<\/h3>\n\n\n\n<p>We can use DB Verify to check the encryption of datafiles.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSYS@CDB2.CDB$ROOT&gt; select file_name from dba_data_files;\n\n&#x5B;oracle@oci-vm1]$ dbv FILE=&amp;lt;file_name&gt;\n\nDBVERIFY: Release 19.0.0.0.0 - Production on Sat May 24 16:04:16 2025\nCopyright (c) 1982, 2019, Oracle and\/or its affiliates.  All rights reserved.\n\nDBVERIFY - Verification starting : FILE = &amp;lt;file_name&gt;\n\nDBVERIFY - Verification complete\n\nTotal Pages Examined         : 113920\nTotal Pages Processed (Data) : 0\nTotal Pages Failing   (Data) : 0\nTotal Pages Processed (Index): 0\nTotal Pages Failing   (Index): 0\nTotal Pages Processed (Other): 1\nTotal Pages Processed (Seg)  : 0\nTotal Pages Failing   (Seg)  : 0\nTotal Pages Empty            : 17265\nTotal Pages Marked Corrupt   : 0\nTotal Pages Influx           : 0\nTotal Pages Encrypted        : 96654   &amp;lt;-- Here shows that blocks are encrypted\nHighest block SCN            : 0 (0.0)\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Re-enable Primary backups<\/h3>\n\n\n\n<p>In case they were paused, to not forget to enable back,<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hybrid Dataguard is a relatively new 19c feature that allows to have one side of a Dataguard configuration not encrypted. This is particularly useful when having a primary on premises and standby on a OCI, where tablespaces need to be encrypted. The main point is that it allows to spare a Advanced Security licenses on [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[51,10,52,6,9],"tags":[54,85],"class_list":{"0":"post-1002","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-cloud","7":"category-dataguard","8":"category-oci","9":"category-oracle","10":"category-security","11":"tag-oci","12":"tag-tde","13":"czr-hentry"},"_links":{"self":[{"href":"https:\/\/anjo.pt\/keyword-oracle\/wp-json\/wp\/v2\/posts\/1002","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/anjo.pt\/keyword-oracle\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/anjo.pt\/keyword-oracle\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/anjo.pt\/keyword-oracle\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/anjo.pt\/keyword-oracle\/wp-json\/wp\/v2\/comments?post=1002"}],"version-history":[{"count":4,"href":"https:\/\/anjo.pt\/keyword-oracle\/wp-json\/wp\/v2\/posts\/1002\/revisions"}],"predecessor-version":[{"id":1007,"href":"https:\/\/anjo.pt\/keyword-oracle\/wp-json\/wp\/v2\/posts\/1002\/revisions\/1007"}],"wp:attachment":[{"href":"https:\/\/anjo.pt\/keyword-oracle\/wp-json\/wp\/v2\/media?parent=1002"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/anjo.pt\/keyword-oracle\/wp-json\/wp\/v2\/categories?post=1002"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/anjo.pt\/keyword-oracle\/wp-json\/wp\/v2\/tags?post=1002"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}