Oracle Refreshable PDB Clone als Standby-DB

By | 27. Juli 2022

Besteht der Wunsch eine fortlaufend synchronisierte Kopie einer Oracle Datenbank als Disaster Recovery Lösung zu betreiben, gibt es vielfältige Möglichkeiten. In der Enterprise Edition bietet sich Oracle Data Guard als bevorzugtes Mittel der Wahl an, da es in der Enterprise Edition Lizenz enthalten ist und eine robuste Synchronisierung ohne Datenverlust ermöglicht. Steht einem nur die Standard Edition zur Verfügung, so kann man neben dem empfohlenen Einsatz von Dritthersteller-Produkten (z.B. Dbvisit Standby) mit der Anwendung des Oracle Feature „Refreshable PDB“ ein ähnliches Ziel, obwohl nicht für diesen Zweck konzipiert, erreichen. Der Aufbau, die Überwachung und das Umschalten einer Standby-PDB im Disaster-Fall erfordert bei diesem Verfahren zwar mehr manuelles Zutun, kann aber dennoch im Einzelfall eine passende Lösung sein. In diesem Beitrag werde ich den Aufbau einer Standby-PDB beschreiben sowie die Vorteile und Nachteile benennen.

Kurzbeschreibung des Verfahrens

In einer zweiten CDB (Standby-CDB) wird über ein zur Primary-CDB führenden Datenbanklink eine Kopie der Primary-PDB erstellt. Die Primary-PDB muss dazu entweder lesend oder schreibend geöffnet und die primäre CDB im Archivelog Mode sein. Der so erzeugte PDB-Klon (Standy-PDB) wird dann in den automatischen Refresh Mode versetzt, bei dem ein Job erzeugt wird, der in einem festen Intervall (z.B. minütlich) über den Datenbanklink die Archivelogs und eine Ad-hoc-Kopie des aktuellen Redologs der Primary-CDB ausliest und die Änderungen gegen die Standby-PDB nachfährt. Die Standby-PDB hängt dabei der Primary-PDB aber immer zeitlich ein wenig hinterher (nicht absolut synchron). Im Disaster-Fall kann bei einem Ausfall der Primary-PDB die Standby-PDB geöffnet werden und den Betrieb übernehmen. Da es normalerweise nicht möglich ist eine Refreshable PDB (hier die Standby-PDB) zu öffnen, wenn die Quell-PDB (hier die Primary PDB) über den Datenbanklink nicht erreichbar ist, bedarf es einen kleinen Workaround, den ich entwickelt habe und in diesem Artikel weiter unten genauer beschreiben werde.

Eigenschaften

  • Auch in der Standard Edition 2 verfügbar
  • Bis auf die reguläre Lizenzierung der Standby-Datenbank fallen keine weiteren Kosten für zu lizenzierende Optionen oder Drittsoftware an.
  • Werden neue Datafiles in der Primary-PDB hinzugefügt, so werden diese auch automatisch in der Standby-PDB angelegt.
  • Die Informationen zur Synchronisierung der Standby-DB werden von der Standby-Seite aus von der Primary-CDB gelesen (Pull).
  • Ein Netzwerkausfall führt nicht zu einem GAP, solange die Archivelogs auf der Primary-Site noch verfügbar sind.
  • Beim Synchronisieren wird mittels einer Ad-hoc-Kopie auch der Inhalt des aktuellen Redologs gelesen. Dadurch fällt der Datenverlust im DR-Fall sehr gering aus.
  • Der maximale Datenverlust (Recovery Point Objective -RPO) wird nur durch das Refresh-Intervall der Standby-PDB bestimmt (kleinstes Intervall 1 Minute).
  • Die Standby-PDB kann zwischendurch lesend geöffnet werden. Die Synchronisierung wird dabei angehalten.

Vorraussetzung für das hier beschriebene Verfahren

  • Oracle 19c, da es erst in der Version möglich ist einen DB Link auf die eigene CDB zeigen zu lassen.
  • Genügend Speicherplatz in der Standby-CDB, um eine erforderliche Dummy-PDB anzulegen (max. 6 GB).
  • Die maximale Anzahl der PDBs in der Standby-CDB darf noch nicht erreicht sein (SE2 = 3).
  • Primary-CDB muss im Archivelog Mode sein.
  • Primary-CDB muss im Force Logging Mode sein.
  • Angepasstes Archivelog-Backup der Primary-CDB,  welches verhindert, dass Archivelogs sofort nach der Sicherung gelöscht werden und diese dann für eine Synchronisation nicht mehr zur Verfügung stehen.
  • Vorzugsweise die Verwendung von Oracle Managed Files (OMF). Falls dies nicht gewünscht muss der Parameters PDB_FILE_NAME_CONVERT genutzt werden.
  • Vorzugsweise die Verwendung einer Recovery Area (FRA) als Speicherort der Archivelogs der Primary-CDB.
  • Verwendung von Local UNDO für die Primary-PDB.

Beispiel

Im nachfolgenden Beispiel beschreibe ich den Aufbau eine Refreshable Standby-PDB, deren Betrieb und den Failover. Aus Übersichtsgründen habe ich die PDB$SEED und ggf. weitere PDBs der Primary-CDB nicht dargestellt. Der Einfachheit halber benutze ich die bestehenden User SYSTEM und SYS für den Aufbau und den Betrieb der Refreshable-PDB. Es ist aber durchaus möglich eigene User mit den erforderlichen Berechtigungen zu nutzen.

Folgende Namen werden verwendet.

Primary-Server
Primary-Server-Name = prmysrv
Primary-CDB-Name = CDBPRMY
Primary-PDB-Name = MYPDB

Standby-Server
Standby-Server-Name = stdbysrv
Standby-CDB-Name = CDBSTDBY
Standby-PDB-Name = MYPDBSBY (nach Failover MYPDB)

Aufbau Standby-Server und Standby-CDB

Zunächst muss auf einem zweiten Server die Oracle Datenbanksoftware analog des Primary-Server installiert werden (Edition, Version, Patchlevel) und eine leere Standby-CDB identisch zur Primary-CDB angelegt werden (Optionen, Zeichensatz).  Die Standby-CDB muss genauso lizenziert sein wie die Primary-CDB.

PDB Standby 1

Vorbereitung Primary-CDB

Für das spätere Erstellen des Klons muss es in der Primary-PDB es einen User geben, der die Berechtigung eine PDB zu erstellen erhält. Der Einfachheit halber nutze ich hier als „Cloning-User“ den bestehenden User SYSTEM der Primary-CDB und sorge mit dem Argument „container=all“, dass die Berechtigung in alle PDBs der Primary-CDB vererbt wird. Des Weiteren ist es empfehlenswert, dass die Primary-CDB in den Force Logging Mode versetzt wird, damit alle Änderungen der Primary-CDB zwingend in die Redologs geschrieben werden.

CBBPRMY:

sqlplus / as sysdba
SQL> grant create pluggable database to system container=all;
SQL> alter database force logging;

 


Erstellung Datenbanklink von der Standby-CDB zur Primary-PDB

In der Standby-CDB wird nun als User SYS ein Datenbanklink erzeugt, über den sich die Standby-CDB mit dem Cloning-Users SYSTEM zur Standby-PDB verbinden kann. Über diesen Datenbanklink wird nicht nur die initiale Kopie der Primary-PDB erzeugt, sondern nachfolgend auch die Standby-PDB mit der Primary-PDB fortlaufend synchronisiert.

CDBSTDBY:

sqlplus / as sysdba
SQL> create database link PDBPRMY_LINK connect to system identified by SectretPW using '//prmysrv:1521/mypdb';

PDB Standby 2


Erstellung Standby-PDB

Die Standby-PDB wird nun aus der Primary-PDB über den zuvor angelegten Datenbanklink erzeugt.

CDBSTDBY:

SQL> create pluggable database MYPDBSBY from MYPDB@PDBPRMY_LINK refresh mode manual;

Nach dem Anlegen der Standby-PDB befindet sich diese im Status Mounted und im Refresh Mode.

PDB Standby 3


Aktivierung automatischer Refresh

Damit nun die Änderungen der Primary-PDB automatisch in der Standby-PDB nachgefahren werden, muss das gewünschte Refresh Mode Intervall eingestellt werden. Dieses Intervall bestimmt den maximalen Datenverlust (RPO), sollte es zu einem Ausfall der Primary-Seite kommen. Geringere Werte als 1 Minute sind hier nicht möglich. Mit dem Setzen des Refresh Mode Intervalls wird im Hintergrund ein Datenbankjob im SYS-Schema erzeugt, der in dem festgelegten Intervall sich über den Datenbanklink mit der Primary-PDB verbindet und die Änderungen aus den Archivelogs und einer Ad-hoc-Kopie des aktuellen Redologs (partial_archivelog) liest und diese in der Standby-PDB nachfährt.

CDBSTDBY:

SQL> alter pluggable database MYPDBSBY refresh mode every 1 minutes;

PDB Standby 4

 

Beispiel des automatisch angelegten Refresh-Job der Standby-CDB

JOB_CREATOR:     SYS
JOB_NAME:        MYPDBSBY_4257033814_REFRESH 
REPEAT_INTERVAL: FREQ = MINUTELY; INTERVAL = 1 
JOB_ACTION: 
declare
  cursor integer :=
  sys.dbms_sql.open_cursor(security_level => 2);
begin
  sys.dbms_sql.parse(
  c => cur,
  statement => 'alter pluggable database refresh',
  language_flag => sys.dbms_sql.native,
  container => 'MYPDBSBY');
  sys.dbms_sql.close_cursor(c=>cur);
end;

 


Überwachung der Synchronität (GAP)

Möchte man feststellen, ob die Standby-PDB einigermaßen synchron mit der Primary-PDB ist, so kann man dies über folgende Abfragen in der Standby-CDB überprüfen.

Anzeige des Status und aktueller Timestamp der Primary-PDB

CDBSTDBY:

set linesize 130
col con_name for a10
col refresh_mode for a12
col current_scn for 999999999999 head "CURRENT_SCN"

select name pdb_name, open_mode, status, current_scn,
to_Char(scn_to_timestamp(current_scn),'DD.MM.YYYY HH24:MI:SS') "TIMESTAMP_PRIMARY"
from v$pdbs@PDBPRMY_LINK right join dba_pdbs@PDBPRMY_LINK using(con_id,creation_time,dbid)
cross join (select dbid cdb_dbid,current_scn from v$database@PDBPRMY_LINK )
where pdb_name = 'MYPDB';

Output:

PDB_NAME OPEN_MODE  STATUS  CURRENT_SCN TIMESTAMP_PRIMARY
-------- ---------- ------- ----------- -------------------
MYPDB    READ WRITE NORMAL  1360015     23.06.2022 14:07:19

 


Anzeige des Status und aktueller Timestamp der Standby-PDB

CDBSTDBY:

set linesize 130
col con_name for a10
col refresh_mode for a12
col last_refresh_scn for 999999999999 head "REFRESH_SCN"
select name pdb_name, open_mode, status, refresh_mode, refresh_interval, last_refresh_scn,
to_Char(scn_to_timestamp(last_refresh_scn),'DD.MM.YYYY HH24:MI:SS') "TIMESTAMP_STANDBY"
from v$pdbs right join dba_pdbs using(con_id,creation_time,dbid)
cross join (select dbid cdb_dbid,current_scn from v$database)
where pdb_name = 'MYPDBSBY';

Output:

PDB_NAME OPEN_MODE  STATUS     REFRESH_MODE REFRESH_INTERVAL REFRESH_SCN TIMESTAMP_STANDBY
-------- ---------- ---------- ------------ ---------------- ----------- -------------------
MYPDBSBY MOUNTED    REFRESHING AUTO                        1 1359925     23.06.2022 14:06:16

Ein Vergleich zwischen des Timestamps der Standby-PDB mit dem Timestamp der Primary-PDB zeigt auf wieweit der Standby-PDB der Primary-PDB zeitlich hinterherhängt (Hier 1 Minuten und 3 Sekunden).


Failover im Disasterfall

Fällt die Primary-PDB aus und soll die Standby-PDB den Datenbankbetrieb übernehmen, so muss man einen sogenannten Failover durchführen. Bei einem Failover wird die Standby-PDB schreibend geöffnet. Es ist empfehlenswert mir der im vorherigen Abschnitt gezeigte Abfrage vorher noch zu prüfen, welchen Timestamp die Standby-PDB hat, um den Datenverlust bewerten zu können.

PDB Standby 13

 

Problem

Um die Standby-PDB schreibend öffnen zu können, muss man den Refresh Mode deaktivieren. Das Oracle Feature Refreshable PDB lässt diese aber nicht zu, wenn die Standby-CDB die Primary-PDB nicht über den Datenbanklink erreicht! Versucht man es, bekommt man den Fehler: „ORA-17629: Cannot connect to the remote database server„. Einen nachvollziehbaren technischen Grund gibt es meiner Ansicht dafür nicht. Wenn ich eine Standby-PDB aber nur öffnen kann, wenn die Primary-PDB erreichbar ist, schließt dies eigentlich eine Verwendung als Disaster-Recovery-Lösung aus! Diesen Umstand fand ich sehr unbefriedigend und habe mich auf die Suche nach einer Möglichkeit gemacht, um die Standby-PDB dennoch öffnen zu können.

Workaround

Ich habe herausgefunden, dass beim Deaktivieren des Refresh Modes lediglich geprüft wird, ob der Datenbanklink vorhanden ist und sich eine Verbindung mit einer PDB mit dem Namen der Primary-PDB herstellen lässt. Es ist also irrelevant, ob es sich dabei um die wirkliche Primary-PDB handelt oder um einen Dummy! Als Workaround muss man also nur den Datenbanklink neu erstellen und diesen auf eine Dummy-PDB zeigen lassen, die so heißt wie die Primary-PDB. Mein Workaround sieht also so aus, dass ich in der Standby-CDB aus der PDB$SEED eine neue zusätzliche PDB mit dem Namen Primary-PDB erstelle und im Anschluss den Datenbanklink neu anlege, sodass er auf die Dummy-PDB zeigt. Nun lässt sich der Refresh-Mode der Standby-PDB ohne weiteres deaktivieren und die Standby-PDB öffnen. Der zusätzliche Platz, den ich für die Dummy-PDB benötige ist sehr gering, da es sich ja nur um eine frische PDB ohne Anwendungsdaten handelt. Woraus man allerdings achten sollte, dass man die maximal erlaubte Anzahl von PDBs pro CDB nicht überschreitet. In der Standard Edition 2 in der Version 19c ist diese Zahl drei. Da für einen kurzen Zeitpunkt die Dummy-PDB und die Standby-PDB nebeneinander in der selben CDB existieren, muss die Standby-PDB zunächst einen anderen Namen haben als die Primary-PDB. Die Standby-PDB wird, nachdem die Dummy-PDB wieder gelöscht wurde, einfach auf den Namen der Primary-PDB umbenannt, um den Betrieb übernehmen zu können.

CDBSTDBY:

Dummy-PDB anlegen in Standby-CDB

sqlplus / as sysdba
SQL> create pluggable database MYPDB admin user pdbadmin identified by SecretPW roles=(DBA) default tablespace users;
SQL> alter pluggable database MYPDB open;

Datenbanklink neu anlegen in Standby-CDB

SQL> drop database link PDBPRMY_LINK;
SQL> create database link PDBPRMY_LINK CONNECT TO pdbadmin IDENTIFIED BY SecretPW USING '//stdbysrv:1521/mypdb';

PDB Standby 14

Standby-PDB schreiben öffnen

SQL> alter pluggable database MYPDBSBY refresh mode manual;
SQL> alter pluggable database MYPDBSBY refresh mode none;
SQL> alter pluggable database MYPDBSBY open;

PDB Standby 15

Dummy-PDB und Datenbanklink löschen

SQL> alter pluggable database MYPDB close immediate;
SQL> drop pluggable database MYPDB including datafiles;
SQL> drop database link PDBPRMY_LINK;

Standby-PDB umbenennen, sodass sie den Betrieb übernehmen kann

SQL> alter pluggable database MYPDBSBY close immediate;
SQL> alter pluggable database MYPDBSBY open restricted;
SQL> alter session set container = MYPDBSBY;
SQL> alter database rename global_name to MYPDB;
SQL> alter pluggable database MYPDB close;
SQL> alter pluggable database MYPDB open;

Nach dem Failover können sich die Clients mit dem Service-Namen der Primary-PDB dann mit der Standby-PDB verbinden.

PDB Standby 17


Client-Failover-Verbindungsbeschreibung

Damit sich ein Client nach einem Failover mit der Standby-PDB verbinden kann, muss die Verbindungsbeschreibung entsprechend konfiguriert werden.

Beispiel Eintrag tnsnames.ora

MYPDB =
  (DESCRIPTION =
   (ADDRESS_LIST =
     (LOAD_BALANCE = OFF)
     (FAILOVER = ON)
     (ADDRESS = (PROTOCOL = TCP)(HOST = oradbprmy.rz.de)(PORT = 1521))
     (ADDRESS = (PROTOCOL = TCP)(HOST = oradbstdby.rz.de)(PORT = 1521))
   )
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = mypdb)
    )
)

Beispiel Java-Anwendung

jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(LOAD_BALANCE=OFF)(FAILOVER=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=oradbprmy.vbox.de)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=oradbstdby.vbox.de)(PORT=1521)))(CONNECT_DATA =(SERVER=DEDICATED)(SERVICE_NAME = mypdb)))

 


Anpassung Archivelog-Backup-Strategie

Problem: Wenn die Archivelogs der Primary-CDB gleich im Anschluss einer Sicherung gelöscht werden, stehen diese nicht mehr für eine Synchronisation mit der Standby zur Verfügung. Dies hat zur Folge, dass u.U. die Standby-PDB nicht mehr synchronisiert werden kann!

Beispiel Sicherung Datenbank und Archvelogs mit anschließendem Löschen der Archivelogs

RMAN> backup database plus archivelog delete input;

PDB Standby 11

Lösung:  Der DBA muss dafür sorgen, dass die Archivelogs noch eine Zeitlang nach einer Sicherung zur Verfügung stehen, bevor diese gelöscht werden!

Beispiel:

RMAN> backup database plus archivelog;
RMAN> change archivelog from time 'sysdate-2' uncatalog;
RMAN> delete noprompt obsolete;
RMAN> catalog recovery area noprompt;

In dem o.a. Beispiel werden die Archivelogs der letzten zwei Tage aus dem RMAN-Repository entfernt, sodass diese bei einem nachfolgenden Löschen der nicht mehr benötigten Datenbanksicherungen (delete nompromt obsolete), und unabhängig von der eingestellten Retention Policy der Datenbank, nicht gelöscht werden. Anschließend werden die Archivelogs wieder dem Repository hinzugefügt, sodass diese für ein Restore und Recovery wieder zur Verfügung stehen. Die in dem Beispiel gewählten 2 Tage gewährleisten, dass auch nach einem Netzwerkausfall zwischen Primary und Standby oder einem 2-tägigen Ausfall der Standby-PDB diese im Anschluss noch mit der Primary-PDB nachsynchronisiert werden kann.


Standby-PDB lesend öffnen

Man kann die Standby-PDB lesend öffnen ohne die Standby-PDB wieder anschließend neu aufbauen zu müssen. Beim lesend öffnen wird die Synchronisierung mit der Primary-PDB unterbrochen. Wenn man die Standby-PDB wieder schließt (Status Mounted) wird die Synchronisierung automatisch fortgeführt. Dies eröffnet einem die Möglichkeit sich den Inhalt der Datenbank vor einem Failover einmal anzuschauen. .

CDBSTDBY:

sqlplus / as sysdba

Standby-PDB lesend öffnen

SQL> alter pluggable database MYPDBSBY open read only;

Standby-PDB wieder schließen

SQL> alter pluggable database MYPDBSBY close;

 

 


Synchronisierung mit lokalen Archivelogs

Möchte man Archivelogs zur Synchronisation nutzen, die nicht über den Datenbanklink zur die Primary-Instance ausgelesen werden, dann kann man die Standby-PDB dazu bringen, diese von einem anderen Ort zu lesen. Vielleicht hat man auf dem Standby-Server fehlende Archivelogs der Primary-PDB aus einer Sicherung wiederhergestellt, die man nun für die Synchronisation benötigt. Oder die Archivelogs werden der Standby-Seite über ein Netzlaufwerk zur Verfügung gestellt. Zu diesem Zweck gibt es den Parameter remote_recovery_file_dest, der in der Standby-PDB auf den Pfad in dem sich die gewünschten Archivelogs befinden gesetzt wird. Da man in einer PDB, die sich im Status Mounted befindet keine Parameter setzten kann, muss man diese kurzzeitig in den Read Only Mode versetzen.

CDBSTDBY:

sqlplus / as sysdba

Standby-PDB Read Only öffnen

SQL> alter pluggable database MYPDBSBY open read only;

Parameter in der Standby-PDB setzen

SQL> alter session set container = MYPDBSBY; 
SQL> alter system set remote_recovery_file_dest='/u02/remote_arc';

Standby-PDB wieder schließen und mit Hilfe der jetzt zur Verfügung stehenden Archivelogs aktualisieren

SQL> alter pluggable database MYPDBSBY close;
SQL> alter pluggable database MYPDBSBY refresh;

PDB-Standby-18


Möchte man, dass die Synchronisierung wieder von der Primary-PDB stattfindet und nicht mehr von den lokal zur Verfügung stehenen Archivelogs, so muss man den Parameter einfach wieder löschen.

CDBSTDBY:

sqlplus / as sysdba

Standby-PDB Read Only öffnen

SQL> alter session set container = MYPDBSBY;
SQL> alter pluggable database open read only;

Parameter in der Standby-PDB löschen

SQL> alter system reset remote_recovery_files_dest;

Standby-PDB wieder schließen

SQL> alter pluggable database close;

Sobald der Parameter gelöscht wurde und die PDB wieder geschlossen wurde, versucht die Standby-PDB sich wieder über den Datenbanklink zur Primary-PDB zu aktualisieren.

 

 


Fazit und Empfehlung

Die von mir beschriebene Methode mit Hilfe des Oracle Feature „Refreshable PDB“ eine Standby-Datenbank als Disaster Recovery Lösung zu nutzen, ist aus meiner Sicht eine gute Möglichkeit, wenn man keine Enterprise Edition besitzt oder keine Drittanbietersoftware einsetzen möchte. Bevor man sich für diese Methode entscheidet, sollte man aber berücksichtigen, dass dieses Feature nicht für dieses Zweck von Oracle entwickelt wurde. Ob der von mir beschriebene Workaround zum Öffnen der Standby-PDB im Failover-Fall auch so in künftigen Versionen funktioniert, vermag ich nicht sagen. In jedem Fall sollten man einen Failover testen und den Status und den GAP zwischen Primary-PDB und Standby-PDB regelmäßig monitoren, um Probleme schnell zu identifizieren und beheben zu können. Generell empfehle ich für alle Schritte (Aufbau Standby-PDB, GAP-Monitoring, Synchronisierung, Failover) eigene Scripte vorzubereiten, die es dem DBA und seinen Vertretern auch in stressigen Situationen und unter Zeitnot ein fehlerfreien Failover durchzuführen.