Migrate to Oracle 26ai without surprises (Data Guard)

From non-CDB with Data Guard to CDB (multitenant)

Table of Contents

In a previous article, I showed you how to upgrade a 19c non-CDB database to 26ai, which turned out to be fairly straightforward — but what if the database also has a physical standby in the mix?

Well, that situation is much more complicated, especially if you also have encrypted tablespaces (TDE). But don’t worry: if you follow these steps exactly, you won’t have any problems, and you’ll come out looking like a hero!

Warning

When I began writing this article, AU 26.4.260701 was available, but it was impossible to get past the analyze phase, since it fails with: checkName=”PLUG_NK_TBS_BLKSZ_TARGET_NK_CACHE_ZERO”.

This is an issue tracked under bug 39758946 (see KB921107), which forces us to use AU 26.3.260401 instead.

Starting point

We start with the Oracle RAC database orcl1 and its physical standby orcl2, both fully operational. We’ve also prepared the containers orcl3 and its physical standby orcl4, which will be our final destinations after the upgrade to 26ai.

We’ll reuse the existing datafiles, which are encrypted (Transparent Data Encryption) for an extra layer of security.

sourcetarget
db_nameorclorcl
db_unique_nameorcl1orcl2orcl3orcl4
roleprimarystandbyprimarystandby
instance_nameorcl1_1, orcl1_2orcl2_1orcl3_1, orcl3_2orcl4_1
servicesorcl_rw orcl_ro
version19.3123.26.2
TDE keystore passwordRigyoTasEnuhyu5#TarojoxobOv#n4Wo

Getting ready: primary

First, we’ll generate the AutoUpgrade configuration file named upg_dg.cfg. Including the manage_standbys_clause parameter is crucial for proper functioning in our scenario.
# Created by AutoUpgrade Composer
# Upgrade, UpgType: noncdb2cdb, FileNameConvert: nocopy

global.global_log_dir=/home/oracle/autoupgrade/log
global.keystore=/home/oracle/autoupgrade/keystore

upg1.sid=orcl1_1
upg1.log_dir=/home/oracle/autoupgrade/log/orcl1_Upgrade
upg1.source_home=/u01/app/oracle/19.0.0/db_1
upg1.target_home=/u01/app/oracle/23.0.0/db_1
upg1.target_cdb=orcl3_1
upg1.target_pdb_name=orcl
upg1.manage_standbys_clause=standbys=all

Setting standbys=all specifies that all the redo generated by the plug-in operation from database orcl1 to orcl3 must be applied immediately on its physical standby, orcl4.

Since we’re using TDE, we can’t forget to register the keystore passwords into the AutoUpgrade wallet — first for database orcl1 (instance orcl1_1), and then for database orcl3 (instance orcl3_1).

If your environment doesn’t employ TDE, you can omit this step.

java -jar autoupgrade.jar \
-config upg_dg.cfg \
-load_password

Processing config file ...

Starting AutoUpgrade Password Loader - Type help for available options
Creating new AutoUpgrade keystore - Password required
Enter password: *************
Enter password again: *************
AutoUpgrade keystore was successfully created

TDE> save
Convert the AutoUpgrade keystore to auto-login [YES|NO] ? YES
TDE>

TDE> add orcl1_1
Enter your secret/Password: *************
Re-enter your secret/Password: *************

TDE> add orcl3_1
Enter your secret/Password: *************
Re-enter your secret/Password: *************
TDE> save
TDE> exit

AutoUpgrade Password Loader finished - Exiting AutoUpgrade

Getting ready: standby

As we saw in the previous article, AutoUpgrade takes care of registering orcl1‘s datafiles in the orcl3 container, but on the physical standby side, there’s a minor issue: the orcl4 container is unaware of the location of orcl2‘s datafiles.

To enable orcl4 to find the datafiles of the upcoming PDB and apply redo from orcl3, we’ll need to manually set up directories and ASM aliases, so that things end up looking like this:

We’ll utilize the script named alias.sql to retrieve orcl2‘s GUID and its datafile list, then generate the required mkdir and mkalias commands.

set pagesize 0
set linesize 300
set feedback off
set trimspool on
spool alias_noncdb.cmd
set serveroutput on size unlimited
DECLARE
  v_DG_CDB  varchar2(10) := 'DATA';
  v_CDB     varchar2(10) := 'ORCL4';
  v_GUID    varchar2(32);
  v_PDB_DIR varchar2(100);
  v_DF_DIR  varchar2(100);
BEGIN
  SELECT guid 
    INTO v_GUID
    FROM v$containers;
  v_PDB_DIR := '+'||v_DG_CDB|| '/' || v_CDB || '/' || v_GUID;
  v_DF_DIR := v_PDB_DIR ||'/DATAFILE/';
    
  dbms_output.put_line( 'mkdir '|| v_PDB_DIR );
  dbms_output.put_line( 'mkdir '|| v_DF_DIR );
  FOR df in (
              SELECT
                name,
                REGEXP_SUBSTR(
                  REPLACE(name, '.', '_'),
                  '[^/]+$'
                ) alias
                FROM v$datafile
               ORDER BY file#
            )    
  LOOP
    dbms_output.put_line(
      'mkalias ' || df.name ||' '|| v_DF_DIR || df.alias );
  END LOOP;
  dbms_output.put_line(
      'ls -l '|| v_DF_DIR );  
END;
/
exit
After connecting to the orcl2 database, we execute the alias.sql script to create the alias_noncdb.cmd file.
$ . orcl2.env
Oracle Home: /u01/app/oracle/19.0.0/db_1
Oracle SID: orcl2_1

$ sqlplus / as sysdba @alias.sql

SQL*Plus: Release 19.0.0.0.0 - Production on Wed Aug 5 14:10:22 2026
Version 19.31.0.0.0

Copyright (c) 1982, 2026, Oracle.  All rights reserved.


Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.31.0.0.0

mkdir +DATA/ORCL4/584193FA481692D6E0638200A8C0A234
mkdir +DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/
mkalias +DATA/ORCL2/DATAFILE/system.306.1240425485 +DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/system_306_1240425485
mkalias +DATA/ORCL2/DATAFILE/sysaux.315.1240425485 +DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/sysaux_315_1240425485
mkalias +DATA/ORCL2/DATAFILE/undotbs1.280.1240425487 +DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/undotbs1_280_1240425487
mkalias +DATA/ORCL2/DATAFILE/undotbs2.310.1240425487 +DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/undotbs2_310_1240425487
mkalias +DATA/ORCL2/DATAFILE/users.275.1240427129 +DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/users_275_1240427129
ls -l +DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/

Disconnected from Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.31.0.0.0

$ ls -la alias_noncdb.cmd
-rw-r--r--. 1 oracle oinstall 814 Aug  5 14:10 alias_noncdb.cmd
We’ll now run asmcmd to execute the commands in alias_noncdb.cmd, which completes the setup on orcl4.
$ . grid.env
Oracle Home: /u01/app/grid/23.0.0/grid_1
Oracle SID: +ASM

$ asmcmd < alias_noncdb.cmd
ASMCMD> ASMCMD> ASMCMD> ASMCMD> ASMCMD> ASMCMD> ASMCMD> ASMCMD>
Type      Redund  Striped  Time             Sys  Name
DATAFILE  UNPROT  COARSE   AUG 05 14:00:00  N    sysaux_315_1240425485 => +DATA/ORCL2/DATAFILE/SYSAUX.315.1240425485
DATAFILE  UNPROT  COARSE   AUG 05 14:00:00  N    system_306_1240425485 => +DATA/ORCL2/DATAFILE/SYSTEM.306.1240425485
DATAFILE  UNPROT  COARSE   AUG 05 14:00:00  N    undotbs1_280_1240425487 => +DATA/ORCL2/DATAFILE/UNDOTBS1.280.1240425487
DATAFILE  UNPROT  COARSE   AUG 05 14:00:00  N    undotbs2_310_1240425487 => +DATA/ORCL2/DATAFILE/UNDOTBS2.310.1240425487
DATAFILE  UNPROT  COARSE   AUG 05 14:00:00  N    users_275_1240427129 => +DATA/ORCL2/DATAFILE/USERS.275.1240427129
ASMCMD> exit
$

First things first: validate

We are now prepared to upgrade to 26ai, so we request AutoUpgrade to review our setup and verify that all is correct.
java -jar autoupgrade.jar \
-config upg_dg.cfg \
-mode analyze

AutoUpgrade 26.3.260401 launched with default internal options
Processing config file ...
Loading AutoUpgrade keystore
AutoUpgrade keystore is loaded
+--------------------------------+
| Starting AutoUpgrade execution |
+--------------------------------+
1 Non-CDB(s) will be analyzed
Type 'help' to list console commands
upg> Job 100 completed
------------------- Final Summary --------------------
Number of databases            [ 1 ]

Jobs finished                  [1]
Jobs failed                    [0]

Please check the summary report at:
/home/oracle/autoupgrade/log/cfgtoollogs/upgrade/auto/status/status.html
/home/oracle/autoupgrade/log/cfgtoollogs/upgrade/auto/status/status.log
Once the analysis is complete, we check the status.log file to confirm there were no errors:
==========================================
          Autoupgrade Summary Report
==========================================
[Date]           Wed Aug 05 14:17:17 PET 2026
[Number of Jobs] 1
==========================================
[Job ID] 100
==========================================
[DB Name]                orcl1
[Version Before Upgrade] 19.31.0.0.0
[Version After Upgrade]  23.26.2.0.0
------------------------------------------
[Stage Name]    PRECHECKS
[Status]        SUCCESS
[Start Time]    2026-08-05 14:16:53
[Duration]      0:00:24
[Log Directory] /home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/100/prechecks
[Detail]        /home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/100/prechecks/orcl1_preupgrade.log
                Check passed and no manual intervention needed
------------------------------------------

It's upgrade time

Let’s start by stopping synchronization from orcl1 to orcl2, and then restart orcl2 to ensure it’s in mount state.

$ dgmgrl sys/*********@orcl1_dg
DGMGRL for Linux: Release 19.0.0.0.0 - Production on Wed Aug 05 14:20:12 2026
Version 19.31.0.0.0

Copyright (c) 1982, 2019, Oracle and/or its affiliates.  All rights reserved.

Welcome to DGMGRL, type "help" for information.
Connected to "orcl1"
Connected as SYSDBA.
DGMGRL> show configuration

Configuration - dg_orcl

  Protection Mode: MaxPerformance
  Members:
  orcl1 - Primary database
    orcl2 - Physical standby database

Fast-Start Failover:  Disabled

Configuration Status:
SUCCESS   (status updated 34 seconds ago)

DGMGRL> edit database orcl2 set state='apply-off';
Succeeded.

DGMGRL> show database orcl2

Database - orcl2

  Role:               PHYSICAL STANDBY
  Intended State:     APPLY-OFF
  Transport Lag:      0 seconds (computed 0 seconds ago)
  Apply Lag:          3 minutes 3 seconds (computed 0 seconds ago)
  Average Apply Rate: (unknown)
  Real Time Query:    OFF
  Instance(s):
    orcl2

Database Status:
SUCCESS

$ srvctl stop database -db orcl2 -stopoption immediate

$ srvctl start database -db orcl2 -startoption mount

Here’s a clear overview of the current situation:

Now, the crucial step is to run AutoUpgrade with -mode deploy, then wait patiently.

java -jar autoupgrade.jar \
-config upg_dg.cfg \
-mode deploy

AutoUpgrade 26.3.260401 launched with default internal options
Processing config file ...
Loading AutoUpgrade keystore
AutoUpgrade keystore is loaded
+--------------------------------+
| Starting AutoUpgrade execution |
+--------------------------------+
1 Non-CDB(s) will be processed
Type 'help' to list console commands
upg>

A few minutes later, AutoUpgrade pauses to notify us that we must visit orcl2 and perform a recovery before proceeding.

..
.
----------------- Continue with the manual steps -----------------
There is a job with manual steps pending.
The checkpoint change number is 1064946 for database orcl1_1.
For the standby database <orcl2>, use the checkpoint SCN <1064946> to recover the database.

You can find the SCN information in:
/home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/101/drain/scn.json
Once these manual steps are completed, you can resume job 101
------------------------------------------------------------------
We connect to orcl2, execute recovery up to SCN 1064946, and verify that all datafiles are synchronized to that SCN.
$ . orcl2.env
Oracle Home: /u01/app/oracle/19.0.0/db_1
Oracle SID: orcl2_1

$ sqlplus / as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Wed Aug 5 14:30:10 2026
Version 19.31.0.0.0

Copyright (c) 1982, 2026, Oracle.  All rights reserved.


Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.31.0.0.0

SQL> alter database recover managed standby database until change 1064946;

Database altered.

SQL> select checkpoint_change#, count(*)
from v$datafile_header
group by checkpoint_change#
order by checkpoint_change#;

CHECKPOINT_CHANGE#   COUNT(*)
------------------ ----------
           1064946          5

From this point on, we no longer need the orcl2 database, so we’ll stop and disable it to ensure no one accidentally restarts it. This prevents the plug-in process towards orcl4 from being interrupted.

$ srvctl stop database -db orcl2 -stopoption immediate

$ srvctl disable database -db orcl2
Here’s a clear overview of where we stand right now:
Now we’re ready to return to AutoUpgrade and resume the job.
..
.
upg> resume -job 101
Resuming job: [101][orcl1_1]
upg>
-----------------------Resuming AutoUpgrade-----------------------
AutoUpgrade is resuming the execution for job 101
------------------------------------------------------------------
Next, the upgrade and the non-CDB to CDB conversion process begin.

After a few minutes, the upgrade to 26ai completes successfully. To confirm, we check the status.log file and afterward the orcl1_postupgrade.log file, which guides us on the next steps.

..
.
Job 101 completed
------------------- Final Summary --------------------
Number of databases            [ 1 ]

Jobs finished                  [1]
Jobs failed                    [0]
Jobs restored                  [0]
Jobs pending                   [0]


Please check the summary report at:
/home/oracle/autoupgrade/log/cfgtoollogs/upgrade/auto/status/status.html
/home/oracle/autoupgrade/log/cfgtoollogs/upgrade/auto/status/status.log
status.log
==========================================
          Autoupgrade Summary Report
==========================================
[Date]           Wed Aug 05 15:00:08 PET 2026
[Number of Jobs] 1
==========================================
[Job ID] 101
==========================================
[DB Name]                orcl1
[Version Before Upgrade] 19.31.0.0.0
[Version After Upgrade]  23.26.2.0.0
------------------------------------------
[Stage Name]    GRP
[Status]        SUCCESS
[Start Time]    2026-08-05 14:19:40
[Duration]      0:00:06
[Detail]        Please drop the following GRPs after Autoupgrade completes:
                 AUTOUPGRADE_9212_ORCL11931000
------------------------------------------
[Stage Name]    PREUPGRADE
[Status]        SUCCESS
[Start Time]    2026-08-05 14:19:47
[Duration]      0:00:00
[Log Directory] /home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/101/preupgrade
------------------------------------------
[Stage Name]    PRECHECKS
[Status]        SUCCESS
[Start Time]    2026-08-05 14:19:47
[Duration]      0:00:30
[Log Directory] /home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/101/prechecks
[Detail]        /home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/101/prechecks/orcl1_preupgrade.log
                Check passed and no manual intervention needed
------------------------------------------
[Stage Name]    PREFIXUPS
[Status]        SUCCESS
[Start Time]    2026-08-05 14:20:17
[Duration]      0:00:28
[Log Directory] /home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/101/prefixups
[Detail]        /home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/101/prefixups/prefixups.html
------------------------------------------
[Stage Name]    DRAIN
[Status]        SUCCESS
[Start Time]    2026-08-05 14:38:21
[Duration]      0:00:05
[Log Directory] /home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/101/drain
------------------------------------------
[Stage Name]    DBUPGRADE
[Status]        SUCCESS
[Start Time]    2026-08-05 14:38:26
[Duration]      0:14:33
[Log Directory] /home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/101/dbupgrade
------------------------------------------
[Stage Name]    NONCDBTOPDB
[Status]        SUCCESS
[Start Time]    2026-08-05 14:58:32
[Duration]      0:00:03
[Log Directory] /home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/101/noncdbtopdb
------------------------------------------
[Stage Name]    POSTCHECKS
[Status]        SUCCESS
[Start Time]    2026-08-05 14:58:35
[Duration]      0:00:01
[Log Directory] /home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/101/postchecks
[Detail]        /home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/101/postchecks/orcl1_postupgrade.log
                Check passed and no manual intervention needed
------------------------------------------
[Stage Name]    POSTFIXUPS
[Status]        SUCCESS
[Start Time]    2026-08-05 14:58:36
[Duration]      0:01:15
[Log Directory] /home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/101/postfixups
[Detail]        /home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/101/postfixups/postfixups.html
------------------------------------------
[Stage Name]    POSTUPGRADE
[Status]        SUCCESS
[Start Time]    2026-08-05 14:59:52
[Duration]      0:00:15
[Log Directory] /home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/101/postupgrade
------------------------------------------
[Stage Name]    SYSUPDATES
[Status]        SUCCESS
[Start Time]    2026-08-05 15:00:08
[Duration]      0:00:00
[Log Directory] /home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/101/sysupdates
------------------------------------------
Summary:/home/oracle/autoupgrade/log/orcl1_Upgrade/orcl1_1/101/dbupgrade/upg_summary.log
[dbname]          [orcl1]
==========================================
[container]          [ORCL]
==========================================
[checkname]          TIMESTAMP_MISMATCH
[stage]              POSTCHECKS
[fixup_available]    YES
[runfix]             YES
[severity]           WARNING
[action]             Recompile the objects with timestamp mismatch. Refer to MOS note 781959.1 for more details.
[broken rule]        There are objects whose timestamp are mismatched with its parent objects.
[rule]               Timestamp of dependent objects must coincide with the timestamp of parent objects.
----------------------------------------------------

[checkname]          POST_DICTIONARY
[stage]              POSTCHECKS
[fixup_available]    YES
[runfix]             YES
[severity]           RECOMMEND
[action]             Gather dictionary statistics after the upgrade using the command:    EXECUTE DBMS_STATS.GATHER_DICTIONARY_STATS;
[broken rule]        Oracle recommends gathering dictionary statistics after upgrade.
[rule]               Dictionary statistics provide essential information to the Oracle optimizer to help it find efficient SQL execution plans. After a database upgrade, statistics need to be re-gathered as there can now be tables that have significantly changed during the upgrade or new tables that do not have statistics gathered yet.
----------------------------------------------------

[checkname]          POST_FIXED_OBJECTS
[stage]              POSTCHECKS
[fixup_available]    NO
[runfix]             N/A
[severity]           RECOMMEND
[action]             Gather statistics on fixed objects after the upgrade and when there is a representative workload on the system using the command:    EXECUTE DBMS_STATS.GATHER_FIXED_OBJECTS_STATS;
[broken rule]        Oracle recommends gathering fixed object statistics after upgrade. This recommendation is given for all preupgrade runs.
[rule]               Fixed object statistics provide essential information to the Oracle optimizer to help it find efficient SQL execution plans. Those statistics are specific to the Oracle Database release that generates them, and can be stale upon database upgrade.  For information on managing optimizer statistics, refer to the 19.0.0.0 Oracle Database Upgrade Guide.
----------------------------------------------------

Redo apply stopped?

For orcl1, AutoUpgrade adds its TDE keys to orcl3‘s unified keystore. However, since these keys are stored as external files outside the database, the changes aren’t replicated, meaning these TDE keys aren’t present in orcl4‘s unified keystore.

The immediate outcome is that the encrypted datafiles are not recognized correctly, as shown in the alert_orcl4.log file (lines 31 to 35):

2026-08-05T14:38:22.272467-05:00
Recovery created pluggable database ORCL
ORCL(3):Recovery scanning directory +DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE for any matching files.
ORCL(3):KZTDE:kztsmptc: Missing Key ID: AXzXtD9MUU/Mv7nOMOs4MC0AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ORCL(3):KZTDE:kztsmptc: keystore_type: 3, wallet_type: 1,wallet location: file:+DATA/orcl4/tde/
ORCL(3):KZTDE:kztsmptc: keystore mode: United
ORCL(3):Recovery created file +DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/system_306_1240425485
ORCL(3):Successfully added datafile 8 to media recovery
ORCL(3):Datafile #8: '+DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/system_306_1240425485'
ORCL(3):KZTDE:kztsmptc: Missing Key ID: AXzXtD9MUU/Mv7nOMOs4MC0AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ORCL(3):KZTDE:kztsmptc: keystore_type: 3, wallet_type: 1,wallet location: file:+DATA/orcl4/tde/
ORCL(3):KZTDE:kztsmptc: keystore mode: United
ORCL(3):Recovery created file +DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/sysaux_315_1240425485
ORCL(3):Successfully added datafile 9 to media recovery
ORCL(3):Datafile #9: '+DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/sysaux_315_1240425485'
ORCL(3):KZTDE:kztsmptc: Missing Key ID: AXzXtD9MUU/Mv7nOMOs4MC0AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ORCL(3):KZTDE:kztsmptc: keystore_type: 3, wallet_type: 1,wallet location: file:+DATA/orcl4/tde/
ORCL(3):KZTDE:kztsmptc: keystore mode: United
ORCL(3):Recovery created file +DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/undotbs1_280_1240425487
ORCL(3):Successfully added datafile 10 to media recovery
ORCL(3):Datafile #10: '+DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/undotbs1_280_1240425487'
ORCL(3):KZTDE:kztsmptc: Missing Key ID: AXzXtD9MUU/Mv7nOMOs4MC0AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ORCL(3):KZTDE:kztsmptc: keystore_type: 3, wallet_type: 1,wallet location: file:+DATA/orcl4/tde/
ORCL(3):KZTDE:kztsmptc: keystore mode: United
ORCL(3):Recovery created file +DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/undotbs2_310_1240425487
ORCL(3):Successfully added datafile 11 to media recovery
ORCL(3):Datafile #11: '+DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/undotbs2_310_1240425487'
ORCL(3):KZTDE:kztsmptc: Missing Key ID: AXzXtD9MUU/Mv7nOMOs4MC0AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ORCL(3):KZTDE:kztsmptc: keystore_type: 3, wallet_type: 1,wallet location: file:+DATA/orcl4/tde/
ORCL(3):KZTDE:kztsmptc: keystore mode: United
ORCL(3):WARNING: the following master key for pluggable database 3 tablespace 5 (file # 12) does not exist in the current keystore.
Please check if the master key is successfully imported from the source keystore.
ORCL(3):kcbtse_populate_tbskey: ena 4 flag 0x2f mkloc 0x1
ORCL(3):   encrypted key 102634419002081e5e428baf89376ca72b91f53334e8c84bdd79ca905ffef8f2
ORCL(3):   mkid 7cd7b43f4c514fccbfb9ce30eb38302d
ORCL(3):Recovery created file +DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/users_275_1240427129
ORCL(3):Successfully added datafile 12 to media recovery
ORCL(3):Datafile #12: '+DATA/ORCL4/584193FA481692D6E0638200A8C0A234/DATAFILE/users_275_1240427129'

Since orcl4 cannot process the encrypted redo, synchronization halts automatically. We can easily verify this using DGMGRL:

DGMGRL> show configuration

Configuration - dg_orcl

  Protection Mode: MaxPerformance
  Members:
  orcl3 - Primary database
    orcl4 - Physical standby database
      Error: ORA-16810: Multiple errors or warnings detected for the member.

Fast-Start Failover:  Disabled

Configuration Status:
ERROR   (status updated 36 seconds ago)

DGMGRL> show database orcl4

Database - orcl4

  Role:                PHYSICAL STANDBY
  Intended State:      APPLY-ON
  Transport Lag:       0 seconds (computed 1 second ago)
  Apply Lag:           22 minutes 33 seconds (computed 1 second ago)
  Average Apply Rate:  4.97 MByte/s
  Real Time Query:     OFF
  Instance(s):
    orcl4_1

  Database Error(s):
    ORA-16766: Redo Apply is stopped.

  Database Warning(s):
    ORA-16853: apply lag has exceeded specified threshold

Database Status:
ERROR
To fix this, we’ll manually update the TDE keystore files. First, we’ll stop synchronization and shut down the orcl4 database.
DGMGRL> edit database orcl4 set state='apply-off';
Succeeded.

$ srvctl stop database -db orcl4 -stopoption immediate
Next, we transfer the TDE keystore files from orcl3 (wallet_root=’+DATA/orcl3′) to the server hosting orcl4.
$ . grid.env
Oracle Home: /u01/app/grid/23.0.0/grid_1
Oracle SID: +ASM1

$ asmcmd kscopy +data/orcl3/tde/ewallet.p12 /home/oracle/tde/orcl3
copying +data/orcl3/tde/ewallet.p12 -> /home/oracle/tde/orcl3/ewallet.p12

$ asmcmd kscopy +data/orcl3/tde/cwallet.sso /home/oracle/tde/orcl3
copying +data/orcl3/tde/cwallet.sso -> /home/oracle/tde/orcl3/cwallet.sso

$ scp /home/oracle/tde/orcl3/ewallet.p12 oracle@stdb-vm:/home/oracle/tde/orcl4/. 
ewallet.p12                                            100% 5091     7.4MB/s   00:00
$ scp /home/oracle/tde/orcl3/cwallet.sso oracle@stdb-vm:/home/oracle/tde/orcl4/. 
cwallet.sso                                            100% 5136     7.7MB/s   00:00

We now copy the files into orcl4‘s TDE keystore (wallet_root=’+DATA/orcl4′), ensuring to delete the old files beforehand. Afterward, we restart the database.

$ . grid.env
Oracle Home: /u01/app/grid/23.0.0/grid_1
Oracle SID: +ASM

$ asmcmd rm +data/orcl4/tde/ewallet.p12
$ asmcmd rm +data/orcl4/tde/cwallet.sso 

$ asmcmd kscopy /home/oracle/tde/orcl4/ewallet.p12 +data/orcl4/tde --dbuniquename orcl4
copying /home/oracle/tde/orcl4/ewallet.p12 -> +data/orcl4/tde/ewallet.p12

$ asmcmd kscopy /home/oracle/tde/orcl4/cwallet.sso +data/orcl4/tde --dbuniquename orcl4 --autologin
copying /home/oracle/tde/orcl4/cwallet.sso -> +data/orcl4/tde/cwallet.sso

$ . orcl4.env
Oracle Home: /u01/app/oracle/23.0.0/db_1
Oracle SID: orcl4_1

$ srvctl start database -db orcl4
Finally, we re-enable synchronization and confirm that there are no further issues.
$ dgmgrl sys/*******@orcl3_dg
DGMGRL for Linux: Release 23.26.2.0.0 - Production on Wed Aug 5 15:34:19 2026
Version 23.26.2.0.0

Copyright (c) 1982, 2026, Oracle and/or its affiliates.  All rights reserved.

Welcome to DGMGRL, type "help" for information.
Connected to "orcl3"
Connected as SYSDBA.

DGMGRL> edit database orcl4 set state='apply-on';
Succeeded.

DGMGRL> show configuration

Configuration - dg_orcl

  Protection Mode: MaxPerformance
  Members:
  orcl3 - Primary database
    orcl4 - Physical standby database

Fast-Start Failover:  Disabled

Configuration Status:
SUCCESS   (status updated 18 seconds ago)

DGMGRL> show database orcl4

Database - orcl4

  Role:                PHYSICAL STANDBY
  Intended State:      APPLY-ON
  Transport Lag:       0 seconds (computed 1 second ago)
  Apply Lag:           0 seconds (computed 1 second ago)
  Average Apply Rate:  8.62 MByte/s
  Real Time Query:     ON
  Instance(s):
    orcl4_1

Database Status:
SUCCESS

Wrapping up

The orcl1_postupgrade.log file reminded us to update the dictionary and fixed-object statistics, so we now run the following commands:
execute DBMS_STATS.GATHER_DICTIONARY_STATS;
execute DBMS_STATS.GATHER_FIXED_OBJECTS_STATS;

We must check for any remaining issues after the database plug-in. Once everything is resolved, we can clean up the violations table.

SELECT message, status
  FROM pdb_plug_in_violations 
 WHERE name = 'ORCL'
 ORDER BY time DESC;

exec DBMS_PDB.CLEAR_PLUGIN_VIOLATIONS;
Although orcl1‘s database services are registered in the new PDB orcl (con_id=3 in orcl3), the clusterware-level services are not yet created, requiring manual registration with srvctl.
column name format a20
column network_name format a20

SELECT con_id, name, network_name 
  FROM v$services
 ORDER by con_id, name;

    CON_ID NAME                 NETWORK_NAME
---------- -------------------- --------------------
         1 SYS$BACKGROUND
         1 SYS$USERS
         1 orcl3                orcl3
         1 orcl3XDB             orcl3XDB
         3 orcl                 orcl
         3 orcl1                orcl1
         3 orcl1XDB             orcl1XDB
         3 orcl_ro              orcl_ro
         3 orcl_rw              orcl_rw
$ srvctl config service -db orcl3

$ srvctl add service -db orcl3 -service orcl_rw -pdb orcl -role primary -preferred orcl3_1,orcl3_2
$ srvctl add service -db orcl3 -service orcl_ro -pdb orcl -role physical_standby -preferred orcl3_1,orcl3_2

$ srvctl start service -db orcl3 -service orcl_rw
$ srvctl start service -db orcl3 -service orcl_ro
$ srvctl stop service -db orcl3 -service orcl_ro

$ srvctl status service -db orcl3
Service orcl_ro is not running.
Service orcl_rw is running on instances orcl3_1,orcl3_2
Likewise, database orcl4 lacks its clusterware-level services, so you’ll need to manually register them with srvctl.
$ srvctl config service -db orcl4

$ srvctl add service -db orcl4 -service orcl_rw -pdb orcl -role primary
$ srvctl add service -db orcl4 -service orcl_ro -pdb orcl -role physical_standby

$ srvctl start service -db orcl4 -service orcl_rw
$ srvctl start service -db orcl4 -service orcl_ro
$ srvctl stop service -db orcl4 -service orcl_rw

$ srvctl status service -db orcl4
Service orcl_ro is running
Service orcl_rw is not running.

Mission accomplished: orcl is now operating normally on Oracle Database Server 26ai as a PDB.

Final thoughts

On My Oracle Support, you’ll find note KB117147: Reusing the Source Standby Database Files When Plugging a non-CDB as a PDB into the Primary Database of a Data Guard Configuration, which outlines all the manual steps for the scenario we just walked through.

Once you read it, you’ll agree there are far too many steps — but you’ve just seen how easy it is with AutoUpgrade‘s help: you only need to create the configuration file, run AU a couple of times, and that’s it: everything happens automatically with no errors.

All that’s left on our end is to create the ASM directories and aliases and copy the TDE keys. After a few minutes, your database will be upgraded to 26ai!

Did you find this article interesting? Did you have any doubts? Do you want to suggest a topic to cover? Leave me your comments or contact me right now!

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.

Related Posts

AU rollback: rollback
Patching with AutoUpgrade became very easy, but rolling back still had to be done by hand. Not anymore. Learn how to do it with AutoUpgrade.
Plugin non-CDB
Multitenant is mandatory in Oracle 26ai. Learn how to upgrade from Oracle 19c Non-CDB to 26ai, including the full migration to Container Database (CDB).
Patching the database
Discover how to perform rolling patching to an Oracle RAC database using AutoUpgrade and a Gold Image.

Need Help?

Fill in these details and I will be in touch as soon as possible.