Mit Oracle 26ai wird Data Guard im Multitenant Umfeld deutlich interessanter. Data Guard auf PDB Ebene, nicht auf CDB Ebene. Schon ab 21c gibt es das Feature, aber mit 26ai ist es in eine Version mit LTS gekommen. Die Idee ist auf den ersten Blick sehr attraktiv: Nicht mehr die komplette CDB steht im Mittelpunkt der Data Guard Konfiguration, sondern einzelne PDBs. Gerade in Multitenant Umgebungen eröffnet das neue Möglichkeiten.
Statt komplette CDBs zu schützen und umzuschalten, können einzelne PDBs zwischen zwei unabhängigen CDBs repliziert, geswitcht oder gefailovert werden. Beide CDBs bleiben dabei produktiv und können gleichzeitig eigene Primär- und Standby-PDBs hosten. Damit lassen sich Schutzkonzepte deutlich granularer aufbauen als mit klassischem CDB-Level Data Guard.
In der Theorie klingt das sehr sauber.
In der Praxis war mein erster Testlauf allerdings eine längere Reise durch Wallets, TDE-Keys, Broker-Syntax, GUID-Konflikte und irreführende Fehlermeldungen. Dieser Beitrag ist deshalb keine Wiederholung der Oracle-Dokumentation. Stattdessen beschreibe ich die Einrichtung so, wie sie in meinem Lab tatsächlich abgelaufen ist: inklusive Fehlern, falschen Annahmen und den Lösungen, die am Ende funktioniert haben.
Ausgangssituation
Meine LAB Umgebung besteht aus zwei Database Base Systems in der OCI mit Version 23.26.2 (26ai).
CDB: DB26B_hgd_fra
PDB: DB_A_PRIM
CDB: DB26C_C
PDB: DB_A_STBY (standby von DB_A_PRIM)
Alle Datenbanken verwendeten TDE mit File Keystore.
Die TDE-Konfiguration:
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
wallet_root string /opt/oracle/dcs/commonstore/wa
llets/DB26B_hgd_fra
SQL> show parameter tde_configuration
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
tde_configuration string keystore_configuration=FILE
Die Wallets waren geöffnet:
SQL> select con_id,
status,
wallet_type,
wallet_order,
keystore_mode
from v$encryption_wallet;
2 3 4 5 6
CON_ID STATUS WALLET_TYPE WALLET_OR KEYSTORE
---------- ------------------------------ -------------------- --------- --------
1 OPEN AUTOLOGIN SINGLE NONE
2 OPEN AUTOLOGIN SINGLE UNITED
3 OPEN AUTOLOGIN SINGLE UNITED
Ziel war es, eine PDB aus einer Source-CDB als Physical Standby PDB in einer anderen CDB zu betreiben.
Warum dieser Beitrag?
Die eigentlichen Data-Guard-Broker-Kommandos sind nicht besonders kompliziert.
Was die Einrichtung schwierig gemacht hat, waren die Nebenthemen:
- TDE Wallet vs. Broker Wallet
- DGPDB_INT
- PDB GUIDs
- Keystore-Passwort
- automatische Instantiation
- TDE-Key-Export und -Import
- Redo Apply mit verschlüsseltem Redo
- und ein bisschen Syntax
Besonders wichtig: Viele Fehlermeldungen zeigen nur die Folge, nicht die Ursache.
Ein Beispiel:
ORA-16937: Instantiation of the DGPDB has failed
Das klingt zunächst nach einem Broker-Problem.
Die eigentliche Ursache lag aber tiefer:
ORA-19583
ORA-19849
ORA-28374
Und noch genauer: Es fehlten TDE-Keys.
Einrichtung
Bevor mit der Einrichtung des DG PDB gestartet wird, müssen ein paar Voraussetzungen gemacht werden:
alter database force logging;
ALTER DATABASE FLASHBACK ON;
Zudem wurden die tnsnames.ora für beide CDBs mit den Connectstrings der jeweils anderen DB ergänzt:
DB26C =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = db26c.sub05220704010.vcnag.oraclevcn.com)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = DB26C_C.sub05220704010.vcnag.oraclevcn.com)
)
)
DB26B =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = db26b.sub05220704010.vcnag.oraclevcn.com)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = DB26B_hgd_fra.sub05220704010.vcnag.oraclevcn.com)
)
)
Ein paar Datenbankparameter wurden auch angepasst:
DB26B:
alter system set dg_broker_start=TRUE scope=both;
alter system set log_archive_dest_1='LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=DB26B_hgd_fra' scope=both;
alter system set standby_file_management=AUTO scope=both;
DB26C:
alter system set dg_broker_start=TRUE scope=both;
alter system set log_archive_dest_1='LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=DB26C_C' scope=both;
alter system set standby_file_management=AUTO scope=both;
Dann kann mit der eigentlichen Einrichtung angefangen werden:
1. Wallet für Broker-Logins
Für DG-PDB benötigt der Broker Zugriff auf beide beteiligten CDBs. Dafür wird ein Wallet mit Credentials verwendet.
Dafür wird ein wallet angelegt. Es wird nicht das bereits bestehende TDE Wallet verwendet.
Beispiel für DB26B und DB26C ausgeführt:
mkdir -p $ORACLE_HOME/dbs/wallets
chmod -R 700 $ORACLE_HOME/dbs/wallets
mkstore -wrl $ORACLE_HOME/dbs/wallets/dgpdb -create
Oracle Secret Store Tool Release 23.26.2.0.0DBRU – Production
Version 23.26.2.0.0DBRU
Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved.
Enter password:
Warning: For security reasons, passwords must have at least 16 characters.
Enter password again:
mkstore -wrl $ORACLE_HOME/dbs/wallets/dgpdb -createCredential db26a sys '<password>'
mkstore -wrl $ORACLE_HOME/dbs/wallets/dgpdb -createCredential db26b sys '<password>'
Der erste Test sollte dann funktionieren:
sqlplus /@db26b as sysdba
Tat er aber nicht.
Stattdessen:
ORA-01017: invalid credential or not authorized; logon denied
Ein Login mit Passwort funktionierte dagegen:
sqlplus 'sys/<password>@db26b as sysdba'
Damit war klar: Netzwerk, Password File und SYS-Passwort waren grundsätzlich korrekt. Das Problem musste im Wallet-Login liegen.
Die Ursache war eine fehlende Zeile in der sqlnet.ora:
WALLET_LOCATION =
(SOURCE =
(METHOD = FILE)
(METHOD_DATA =
(DIRECTORY = /u01/app/oracle/product/23.0.0/dbhome_1/dbs/wallets/dgpdb)
)
)
SQLNET.WALLET_OVERRIDE = TRUE
Der entscheidende Parameter ist:
SQLNET.WALLET_OVERRIDE = TRUE
Ohne diese Zeile wird das Wallet nicht so verwendet, wie es für sqlplus /@alias erwartet wird.
Nach der Korrektur funktionierte:
sqlplus /@db26b as sysdba
sqlplus /@db26c as sysdba
2. Vorbereitungen der DG PDB Broker Konfiguration
Zuerst wird im Broker dann auf beiden Seiten eine Broker Config angelegt:
dgmgrl /@db26b
create configuration 'DB26B' CONNECT IDENTIFIER IS db26b;
Configuration "DB26B" created with primary database ""
dgmgrl /@db26c
create configuration 'DB26C' CONNECT IDENTIFIER IS db26c;
Configuration "DB26C" created with primary database ""
ENABLE CONFIGURATION ALL;
Enabled.
Der nächste Schritt im Broker:
DGMGRL> EDIT CONFIGURATION PREPARE DGPDB;
Dabei fragt DGMGRL nach dem Passwort für den internen Benutzer DGPDB_INT.
Bei mir erschien zunächst mehrfach:
ORA-00922: missing or invalid option
Die Ursache war nicht offensichtlich.
Am Ende stellte sich heraus: Das gewählte Passwort war das Problem. Mit bestimmten Sonderzeichen kam der interne SQL-Befehl offenbar nicht zurecht.
Mit einem Passwort ohne problematische Sonderzeichen funktionierte der Befehl.
Meine Empfehlung für den ersten Aufbau:
Für DGPDB_INT zunächst ein Passwort aus Buchstaben und Zahlen und nur Underscore (_) als Sonderzeichen verwenden.
Eins Passwort, welches Beispielhaft funktioniert: OraPDBdg2026__
DGMGRL> EDIT CONFIGURATION PREPARE DGPDB;
Enter password for DGPDB_INT account at DB26B_hgd_fra: OraPDBdg2026__
Enter password for DGPDB_INT account at DB26C_C: OraPDBdg2026__
Prepared Data Guard per Pluggable Database at DB26C_C.
Prepared Data Guard per Pluggable Database at DB26B_hgd_fra.+
3. ADD PLUGGABLE DATABASE und die Keystore Klausel
Der nächste Schritt war laut Anleitung das Hinzufügen der Standby-PDB.
ADD PLUGGABLE DATABASE 'DB_A_STBY' AT DB26C_C
SOURCE IS 'DB_A_PRIM' AT DB26B_hgd_fra
PDBFileNameConvert IS
"'/u02/app/oracle/oradata/DB26B_hgd_fra/DB26B_HGD_FRA/','/u02/app/oracle/oradata/DB26C_C/DB26C_C/'";
Da TDE aktiv war, kam erwartungsgemäß:
ORA-46697: Keystore password required.
Der erste intuitive Versuch war:
ADD PLUGGABLE DATABASE ...
KEYSTORE IDENTIFIED BY "<password>";
Syntax error before or at "IDENTIFIED"
Die korrekte Syntax ist ungewohnt und in der Dokumentation leicht zu übersehen:
ADD PLUGGABLE DATABASE 'DB_A_STBY' AT DB26C_C
SOURCE IS 'DB_A_PRIM' AT DB26B_hgd_fra
PDBFileNameConvert IS
"'/u02/app/oracle/oradata/DB26B_hgd_fra/DB26B_HGD_FRA/','/u02/app/oracle/oradata/DB26C_C/DB26C_C/'" 'KEYSTORE IDENTIFIED BY "<password>"';
Die gesamte Keystore-Klausel muss als zusätzlicher String angegeben werden:
'KEYSTORE IDENTIFIED BY "..."'
Das ist eine der Stellen, an denen man sehr leicht stolpert.
Damit war das Thema allerdings noch nicht erledigt.
4. GUID Konflikt
Ein weiterer Fehler:
ORA-65122: Pluggable database GUID conflicts with the GUID of an existing container.
Zunächst war das überraschend, weil die CDBs auf unterschiedlichen Servern laufen.
Die Prüfung der v$pdbs zeigte auf beiden Seiten eine identische GUID der ersten PDB.
Die wahrscheinlichste Erklärung: Die beiden Base Database Systems wurden zeitgleich mit der gleichen Version erstellt. Da nutzt die OCI vermutlich das selbe Gold Image, so dass die ersten Default PDBs die selbe GUID hatten.
Für DG-PDB ist das ein Problem, denn auf der Ziel-CDB darf keine bestehende PDB dieselbe GUID wie die Source-PDB besitzen. Die Lösung war, die kollidierende PDB auf dem Ziel zu entfernen beziehungsweise eine saubere Zielumgebung zu verwenden.
5. Automatische Instantiation schlägt fehl
Ab Version 23.26.2 sollte die Instantiation automatisch erfolgen, wenn im Data Guard Broker eine PDB Standby angelegt wird. Trotzdem schlug der Vorgang zunächst fehl:

Auf der Suche nach der Ursache in den Logfiles finde ich im Broker Log:
Instantiation of DGPDB DB_A_STBY has failed.
Recovery for DGPDB DB_A_STBY cannot be started until successful instantiation.
Im Alert Log stand zunächst:
Failure to restore or refresh data files for this pluggable database due to ORA-19583.
Failed to copy datafiles for this pluggable database from the source database.
Das klingt zunächst nach einem Problem mit Pfaden, Netzwerk oder File Copy.
Erst im Tracefile zeigte sich die eigentliche Ursache:
ORA-19583: conversation terminated due to error
ORA-19849: error while reading backup piece from service db26b
ORA-28374: typed master key not found in wallet
Damit war klar: Die automatische Instantiation verwendet Restore from Service. Dabei müssen verschlüsselte Source-Datafiles gelesen werden. Dafür benötigt die Target-CDB die TDE-Keys der Source.
Daher muss der folgende Schritt vorher ausgeführt werden:
6. Erster TDE Key Export der Source PDB
Der naheliegende Schritt war, die Keys aus der Source-PDB zu exportieren.
alter session set container=DB_A_PRIM;
administer key management export encryption keys
with secret "ExportSecret123"
to '/tmp/db_a_prim_tdekeys.exp'
force keystore identified by "welcome10-#OCI";
Anschließend wurde die Datei auf die Target-CDB kopiert und dort importiert.
Auf dem Ziel:
alter session set container=CDB$ROOT;
administer key management import encryption keys
with secret "ExportSecret123"
from '/tmp/db_a_prim_tdekeys.exp'
force keystore identified by "welcome10-#OCI"
with backup;
Danach konnte die automatische Instantiation weiterkommen. Im Alert Log war nun zu sehen, dass die Datafiles aus dem Backup Piece restored wurden.
Completed: create pluggable database DB_A_STBY as standby from DB_A_PRIM at db26b_hgd_fra file_name_convert=('/DB26B_hgd_fra/DB26B_HGD_FRA/','/DB26C_C/DB26C_C/') KEYSTORE IDENTIFIED BY *
…
2026-06-11T08:04:26.304695+00:00
DB_A_STBY(4):Restore from backup piece network
DB_A_STBY(4):Full restore complete of datafile 26 /u02/app/oracle/oradata/DB26C_C/DB26C_C/53E52C8563E42EDAE0635300000A52A2/datafile/o1_mf_undotbs1_o2nv0bcm_.dbf. Elapsed time: 0:00:00
DB_A_STBY(4): checkpoint is SCN 5882966 time 06/11/2026 08:04:26 on PDB incarnation 0
DB_A_STBY(4):5867404
DB_A_STBY(4):5876234
DB_A_STBY(4):Restore from backup piece network
2026-06-11T08:04:28.716233+00:00
DB_A_STBY(4):Full restore complete of datafile 25 /u02/app/oracle/oradata/DB26C_C/DB26C_C/53E52C8563E42EDAE0635300000A52A2/datafile/o1_mf_sysaux_o2nv0bnd_.dbf. Elapsed time: 0:00:02
DB_A_STBY(4): checkpoint is SCN 5882972 time 06/11/2026 08:04:26 on PDB incarnation 0
DB_A_STBY(4):4582154
DB_A_STBY(4):Restore from backup piece network
2026-06-11T08:04:31.200088+00:00
DB_A_STBY(4):Full restore complete of datafile 24 /u02/app/oracle/oradata/DB26C_C/DB26C_C/53E52C8563E42EDAE0635300000A52A2/datafile/o1_mf_system_o2nv0dsn_.dbf. Elapsed time: 0:00:03
Das war der erste Durchbruch.
Aber das ist noch nicht das Ende.
7. ORA-28374 nach erfolgreichem Restore
Nachdem die Datafiles erfolgreich erzeugt wurden, gab es ein weiteres Problem. Der Apply startete nicht sauber:
DGMGRL> EDIT PLUGGABLE DATABASE 'DB_A_STBY' AT DB26C_C SET STATE='APPLY-ON';
Fehler im Alert Log:
2026-06-11T08:05:32.802973+00:00
DB_A_STBY(4):Apply slave process (PID=42323) started
DB_A_STBY(4):*** 2026-06-11T08:05:32.867038+00:00
DB_A_STBY(4):Media Recovery Log /u03/app/oracle/fast_recovery_area/DB26C_C/archivelog/2026_06_11/o1_mf_1_20_o2nv09w3_.arc
DB_A_STBY(4):PR00 (PID:42319): Background Media Recovery terminated with error 28374 [krd.c:29437]
2026-06-11T08:05:32.887128+00:00
DB_A_STBY(4):Errors in file /u01/app/oracle/diag/rdbms/db26c_c/DB26C/trace/DB26C_pr00_42319.trc:
ORA-28374: typed master key not found in wallet
DB_A_STBY(4):PR00 (PID:42319): PDBID:4 Managed Recovery not using Real Time Apply [krsm.c:16125]
DB_A_STBY(4):Recovery interrupted!
[krdgp.c:2898] krdgp_check_slaves: Slave PR01 for DGPDB 4 died. slave_cnt=0
[krdgp.c:2898] krdgp_check_slaves: Slave PR02 for DGPDB 4 died. slave_cnt=0
[krdgp.c:2929] krdgp_check_slaves: Slave PR00 for DGPDB 4 exited normally. slave_cnt=0
Das war irritierend, denn die Key-IDs waren inzwischen in V$ENCRYPTION_KEYS sichtbar.
Der entscheidende Hinweis stand nicht in DGMGRL, sondern im Tracefile:

Das war der entscheidende Unterschied.
Vorher fehlte der Key beim Lesen der verschlüsselten Datafiles während Restore from Service.
Jetzt fehlte der Key beim Entschlüsseln der Redo-Informationen.
Der relevante Hinweis:
failed to decrypt on-disk log key
Damit war klar:
Der PDB-Key allein reicht nicht. Der Restore konnte zwar erfolgen, aber die Redo Logs nicht entschlüsselt werden.
8. Die eigentliche Lösung: TDE Key Export aus CDB$ROOT
Die finale Lösung war, die Keys aus dem CDB$ROOT der Source-CDB zu exportieren und im CDB$ROOT der Target-CDB zu importieren.
Auf der Source:
alter session set container=CDB$ROOT;
administer key management export encryption keys
with secret "ExportSecret123"
to '/tmp/source_cdbroot_tdekeys.exp'
force keystore identified by "welcome10-#OCI";
Datei auf das Zielsystem kopieren.
Auf dem Target:
alter session set container=CDB$ROOT;
administer key management import encryption keys
with secret "ExportSecret123"
from '/tmp/source_cdbroot_tdekeys.exp'
force keystore identified by "welcome10-#OCI"
with backup;
Dann wurde die Datenbank einmal rebootet. Anschließend konnte Apply erfolgreich gestartet werden:
DGMGRL> EDIT PLUGGABLE DATABASE 'DB_A_STBY' AT DB26C_C SET STATE='APPLY-ON';
Succeeded.
Damit war die Einrichtung der Standby PDB erfolgreich.

Warum der PDB Key alleine nicht reicht
Meine ursprüngliche Annahme war:
Ich schütze eine PDB, also brauche ich nur die TDE-Keys dieser PDB.
Das war falsch.
Für den Restore der Datafiles kann der PDB-Key ausreichen.
Für Redo Apply werden aber offenbar zusätzliche Key-Informationen aus dem Root-Kontext benötigt. Das erklärt auch, warum die Fehlermeldung so verwirrend war:
V$ENCRYPTION_KEYS zeigte die erwarteten PDB-Key-IDs.
mkstore zeigte die Keys im Wallet.
Trotzdem schlug Redo Apply mit ORA-28374 fehl.
Der Tracefile-Hinweis auf den Redo-Key war entscheidend.
Die Kurzfassung:
DG-PDB mit TDE benötigt nicht nur PDB-Key-Material.
Für Redo Apply müssen auch die relevanten CDB$ROOT-Keys auf dem Ziel vorhanden sein.
Fazit
Oracle 26ai Data Guard auf PDB-Ebene ist ein sehr spannendes Feature.
Gerade für Multitenant-Umgebungen eröffnet es neue Möglichkeiten, weil nicht mehr komplette CDBs geschützt werden müssen. Einzelne PDBs können gezielt repliziert und abgesichert werden.
In Kombination mit TDE ist die Einrichtung aber anspruchsvoller, als es auf den ersten Blick aussieht.
Die wichtigsten Punkte aus meinem Test:
- SQLNET.WALLET_OVERRIDE nicht vergessen
- DGPDB_INT-Passwort einfach halten
- KEYSTORE-Klausel korrekt quoten
- GUID-Konflikte prüfen
- TDE-Keys vor der Instantiation übertragen
- Nicht nur PDB-Keys exportieren
- CDB$ROOT-Keys ebenfalls exportieren/importieren
- Tracefiles lesen
Der wichtigste technische Lerneffekt war:
Für DG-PDB mit TDE reicht der Export der PDB-Keys allein nicht aus.
Für Redo Apply werden auch die relevanten Keys aus CDB$ROOT benötigt.
Nachdem diese Punkte berücksichtigt waren, funktionierte DG-PDB wie erwartet. Für produktive Umgebungen würde ich den TDE-Key-Transfer als festen vorbereitenden Schritt in jede DG-PDB-Implementierung aufnehmen.