Data Guard ist einfach
Jede Oracle Datanbank, die einen gewissen Stellenwert für ein Unternehmen hat, sollte mit einer Standby Datenbank abgesichert werden. Wie man das mit der Standard Edition Two macht, werde ich in einem separaten Blog beschreiben. Hier geht es zunächst darum, einfach, schnell und reproduzierbar eine Data Guard Datenbank aufzubauen.
In der Beschreibung werde ich nicht mehr auf die generelle Funktionisweise von Data Guard und die unterschiedlichen Modi eingehen. Dafür gibt es diverse andere Blogs, unter anderem https://www.carajandb.com/blog/2015/dataguard-protection-modi-de.
Die Konfiguration besteht aus zwei Datenbanken auf zwei Servern:
Primäre Datenbank:
Server: wagner
Datenbankname: RICHARD
DB-Unique-Name: RICHARD_W
Standby Datenbank:
Server: strauss
Datenbankname: RICHARD
DB-Uniquen-Name: RICHARD_S
Datenbank-Version ist 12.2.0
In dem Beispiel werde ich Oracle Managed Files verwenden. In einem weiteren Blog habe ich beschreiben, was bei Oracle Managed Files und Multitenant zu beachten ist (https://www.carajandb.com/blog/2016/multitenant-im-dataguard-umfeld).
Primäre Datenbank
Sie sollten bereits bei der Erstellung der Datenbank den DB-Unique-Name setzen, weil er Einfluss auf die Lage der Datenbankdateien hat. Außerdem hat es sich bewehrt, mit symbolischen Links für die Admin-Verzeichnisse zu arbeiten:
cd /u01/app/oracle/admin mkdir -p RICHARD/config RICHARD/adump RICHARD/dpdump RICHARD/spfile RICHARD/scripts RICHARD/xdb_wallet ln -s RICHARD RICHARD_W mkdir -p /u02/oradata/RICHARD/config mkdir -p /u03/orabackup/RICHARD/config
Als nächstes wird die Datenbank vorbereitet:
sqlplus / as sysdba ALTER SYSTEM SET dg_broker_config_file1='/u02/oradata/RICHARD/config/dg_config1.cfg'; ALTER SYSTEM SET dg_broker_config_file2='/u03/orabackup/RICHARD/config/dg_config2.cfg'; ALTER DATABASE FORCE LOGGING; ALTER SYSTEM SET log_archive_format='%t_%s_%r.arc' scope=spfile; ALTER SYSTEM SET "_query_on_physical"=false SCOPE=spfile; SHUTDOWN IMMEDIATE STARTUP MOUNT; ALTER DATABASE ARCHIVELOG; ALTER DATABASE FLASHBACK ON; ALTER DATABASE OPEN;
HINWEIS: Der Parameter „[inlinecode]_query_on_physical[/inlinecode]“ ist nicht supportet und sollte laut Oracle nicht benutzt werden. Er hilft aber dabei, die Standby Datenbank nicht Read-Only zu öffnen, während der Apply-Prozess aktiv ist. Dadurch würde die Active Data Guard Lizenz benötigt.
Als nächstes werden die Standby Redologs erstellt. Laut Oracle Vorgabe braucht man mind. eine mehr als Online Redologs. Da ich in den meisten Fällen mit drei Redologs pro Thread arbeite, benötige ich hier also 4 Standby Redologs:
ALTER DATABASE ADD STANDBY LOGFILE GROUP 11 size 200M; ALTER DATABASE ADD STANDBY LOGFILE GROUP 12 size 200M; ALTER DATABASE ADD STANDBY LOGFILE GROUP 13 size 200M; ALTER DATABASE ADD STANDBY LOGFILE GROUP 14 size 200M;
Damit ist die primäre Datenbank für Data Guard vorbereitet.
Oracle Net
Als nächstes ist die Oracle Net Konfiguration dran:
Der Listener muss einen statischen Eintrag für die Datenbank erhalten, denn sonst würde sich beim Kopieren mit RMAN die Datenbank „deregistrieren“ und der Duplikate Befehl würde fehlschlagen. Außerdem wird noch ein statischer Eintrag für den Data Guard Broker benötigt.
Ich arbeite gerne mit vorgefertigten Skripten, d.h. mit der Eingabe- und Ausgabeumleitung in der Shell.
cat < $ORACLE_HOME/network/admin/listener.ora SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = RICHARD_W.carajandb.intra) (ORACLE_HOME=/u01/app/oracle/product/12.2.0/dbhome_1) (SID_NAME = RICHARD)) (SID_DESC = (GLOBAL_DBNAME = RICHARD_W_DGMGRL.carajandb.intra) (ORACLE_HOME=/u01/app/oracle/product/12.2.0/dbhome_1) (SID_NAME = RICHARD)) ) EOCAT lsnrctl stop lsnrctl start
Nach dem Listener werden die TNS-Aliase definiert:
Hier empfiehlt sich ein Eintrag für den „normalen“ Betrieb über den Default Service, sowie ein Eintrag, der den jeweiligen Server enthält und über die SID angesprochen wird.
cat < $ORACLE_HOME/network/admin/tnsnames.ora RICHARD_W.carajandb.intra = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = wagner)(PORT = 1521)) (CONNECT_DATA = (SERVICE_NAME = RICHARD_W.carajandb.intra) ) ) RICHARD_S.carajandb.intra = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = strauss)(PORT = 1521)) (CONNECT_DATA = (SERVICE_NAME = RICHARD_S.carajandb.intra) ) ) RICHARD_wagner.carajandb.intra = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = wagner)(PORT = 1521)) (CONNECT_DATA = (SID = RICHARD) ) ) RICHARD_strauss.carajandb.intra = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = strauss)(PORT = 1521)) (CONNECT_DATA = (SID = RICHARD) ) ) EOCAT
Fehlt noch die sqlnet.ora. Das wäre zwar nicht unbedingt erforderlich, aber da ich mit einer Datenbankdomäne arbeite, möchte ich vermeiden, dass ich die immer eintippen muss:
echo "NAMES.DEFAULT_DOMAIN=carajandb.intra" > $ORACLE_HOME/network/admin/sqlnet.ora
Die tnsnames.ora und sqlnet.ora können jetzt per scp auf die Standby Datenbank kopiert werden.
Parameterdatei
In vielen Dokumenten wird aus dem spfile der primären Datenbank eine init.ora erstellt und diese dann auf die Standby Seite kopiert. Ich halte das für zu umständlich, da die „korrekte“ Parameterdatei mit dem RMAN Duplicate kopiert wird. Daher erstelle ich eine sehr rudimentäre init.ora, die nur für das Starten des Duplicate verwendet wird.
Ich erstelle die Datei, so wie andere auch, auf beiden Seiten, damit ich bei Bedarf auch später eine Standby Datenbank wieder aufsetzen kann, selbst wenn es zwischenzeitlich einen Rollentausch gab.
cat < /u01/app/oracle/admin/RICHARD/config/initdup.ora *.compatible='12.2.0.1' *.db_block_size=8192 *.db_domain='carajandb.intra' *.db_name='RICHARD' *.diagnostic_dest='/u01/app/oracle' *.log_archive_format='%t_%s_%r.arc' *.pga_aggregate_target=512M *.remote_login_passwordfile='EXCLUSIVE' *.sga_target=2000M *.undo_tablespace='UNDOTBS1' EOCAT
Auch diese Datei kann 1:1 auf die Standby Seite kopiert werden.
RMAN Skript
Jetzt fehlt nur noch das Skript für den RMAN. Hier muss man aufpassen, da das Skript für die beiden Seiten unterschiedlich sind.
cat < /u01/app/oracle/admin/RICHARD/config/duplicate.rcv connect target sys/manager@RICHARD_S connect auxiliary sys/manager@RICHARD_wagner run{ allocate channel prmy1 type disk; allocate auxiliary channel stby1 type disk; DUPLICATE TARGET DATABASE FOR STANDBY FROM ACTIVE DATABASE DORECOVER SPFILE PARAMETER_VALUE_CONVERT 'RICHARD_S','RICHARD_W','strauss','wagner' SET "db_unique_name"="RICHARD_W" SET "instance_number"="1" NOFILENAMECHECK; } EOCAT
Diese Datei kommt jetzt noch nicht zum Einsatz, weil RICHARD_W ja unsere primäre Datenbank ist.
Standby Datenbank
Ich gehe davon aus, dass auf dem Standby Server noch keine Dateistruktur existiert, d.h. ausschließlich die Datenbanksoftware installiert ist.
Daher müssen wir hier zunächst eine Reihe von Verzeichnissen anlegen:
mkdir -p /u01/app/oracle/admin cd /u01/app/oracle/admin mkdir -p RICHARD/adump RICHARD/dpdump RICHARD/pfile RICHARD/scripts RICHARD/xdbwallet RICHARD/config /u02/oradata/RICHARD/config /u03/orabackup/RICHARD/config ln -s RICHARD RICHARD_S
Jetzt kann man die Umgebungsvariablen, wie üblich über den Befehl oraenv setzen:
echo "RICHARD:/u01/app/oracle/product/12.2.0/dbhome_1:N" >> /etc/oratab ORACLE_SID=RICHARD ORAENV_ASK=NO . oraenv unset ORAENV_ASK
Oracle Net
Die tnsnames.ora und sqlnet.ora Dateien wurden ja bereits vom primären Server übertragen. Es fehlt noch die listener.ora:
cat < $ORACLE_HOME/network/admin/listener.ora SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = RICHARD_S.carajandb.intra) (ORACLE_HOME=/u01/app/oracle/product/12.2.0/dbhome_1) (SID_NAME = RICHARD)) (SID_DESC = (GLOBAL_DBNAME = RICHARD_S_DGMGRL.carajandb.intra) (ORACLE_HOME=/u01/app/oracle/product/12.2.0/dbhome_1) (SID_NAME = RICHARD)) ) EOCAT lsnrctl stop lsnrctl start
RMAN Skript
Schlussendlich muss nur noch das RMAN-Skript erstellt werden, da auch die init.ora schon kopiert wurde:
cat < /u01/app/oracle/admin/RICHARD/config/duplicate.rcv connect target sys/manager@RICHARD_W connect auxiliary sys/manager@RICHARD_strauss run{ allocate channel prmy1 type disk; allocate auxiliary channel stby1 type disk; DUPLICATE TARGET DATABASE FOR STANDBY FROM ACTIVE DATABASE DORECOVER SPFILE PARAMETER_VALUE_CONVERT 'RICHARD_W','RICHARD_S','wagner','strauss' SET "db_unique_name"="RICHARD_S" SET "instance_number"="1" NOFILENAMECHECK; } EOCAT
Damit sind die Vorbereitungen abgeschlossen.
RMAN Duplicate
Als nächstes wird die „Dummy“ Instanz gestartet und das RMAN Duplicate Skript ausgeführt:
sqlplus / as sysdba startup nomount pfile='/u01/app/oracle/admin/RICHARD/config/initdup.ora' exit rman @/u01/app/oracle/admin/RICHARD/config/duplicate.rcv
HINWEIS: Es empfiehlt sich, vor dem Starten des RMAN-Skripts den Connect an Target und Auxiliary auf beiden (!) Servern zu testen.
Data Guard Broker
Jetzt fehlt nur noch die Data Guard Konfiguration. Dafür wird zunächst auf der Standby Datenbank der Broker aktiviert. Außerdem muss noch Flashback Database aktiviert werden, da diese Information beim Duplicate nicht mit übertragen wird.
sqlplus / as sysdba ALTER DATABASE FLASHBACK ON; ALTER SYSTEM SET dg_broker_start=true;
Auf dem primären Server wird jetzt der Broker konfiguriert. Vorher muss auch hier der Broker gestartet werden:
sqlplus / as sysdba ALTER DATABASE FLASHBACK ON; EXIT; dgmgrl / CREATE CONFIGURATION 'RICHARD_DG' AS PRIMARY DATABASE IS 'RICHARD_W' CONNECT IDENTIFIER IS 'RICHARD_W.carajandb.intra'; ADD DATABASE 'RICHARD_S' AS CONNECT IDENTIFIER IS 'RICHARD_S.carajandb.intra' MAINTAINED AS PHYSICAL; EDIT DATABASE 'RICHARD_W' SET PROPERTY StandbyFileManagement='AUTO'; EDIT DATABASE 'RICHARD_S' SET PROPERTY StandbyFileManagement='AUTO'; EDIT DATABASE 'RICHARD_W' SET PROPERTY 'NetTimeout'=60; EDIT DATABASE 'RICHARD_S' SET PROPERTY 'NetTimeout'=60; EDIT DATABASE 'RICHARD_W' SET PROPERTY 'LogXptMode'='SYNC'; EDIT DATABASE 'RICHARD_S' SET PROPERTY 'LogXptMode'='SYNC'; EDIT DATABASE 'RICHARD_W' SET PROPERTY dbDisplayName = 'RICHARD_W.carajandb.intra'; EDIT DATABASE 'RICHARD_S' SET PROPERTY dbDisplayName = 'RICHARD_S.carajandb.intra'; EDIT CONFIGURATION SET PROTECTION MODE AS MAXAVAILABILITY; ENABLE CONFIGURATION
Fertig!
HINWEIS: Trinken Sie jetzt eine Tasse Kaffee!
Warum? Weil es einige Minuten dauern kann, bis die Synchronisation abgeschlossen ist. Erst dann sollten Sie den Data Guard Befehl „SHOW CONFIGURATION“ ausführen. Hoffentlich sieht er dann, wie in dem Beispiel aus:
DGMGRL> show configuration Configuration - RICHARD_DG Protection Mode: MaxAvailability Members: RICHARD_W - Primary database RICHARD_S - Physical standby database Fast-Start Failover: DISABLED Configuration Status: SUCCESS (status updated 28 seconds ago)
Fazit
Mit diesen Skripten bin ich jederzeit in der Lage, die Standby Datenbank neu aufzusetzen, egal ob die primäre Datenbank gerade auf dem Server 1 oder 2 läuft. Bitte beachten Sie in diesem Zusammenhang noch die Verwendung eines DB-Unique-Names, der eine Datenbank „abqualifiziert“, wie z.B. _STANDBY oder ähnlich. Besser Sie verwenden einfache Nummern (S1 / S2) oder Kürzel als Unterscheidungskriterium.
Viel Erfolg
Gut geschrieben und informativ. Gute Arbeit!