Data Guard ist einfach

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

1 Kommentar zu „Data Guard ist einfach“

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Nach oben scrollen