Freitag, 10. August 2012

OracleNet für Clients in einer Data Guard Umgebung

Damit Clients immer auf die aktive Datenbank in einer Data Guard Umgebung kommen, muss die folgende Konfiguration vorgenommen werden.

Umgebung

Wir nehmen die folgende Konfiguration an:
Primary
Host: primhost
ORACLE_SID: mars
db_unique_name: mars
Standby
Host: primhost
ORACLE_SID: mars
db_unique_name: mars_dg
Konfiguration aus Sicht des Clients
Für die Clients soll der Oracle Service "marsdb" verfügbar gemacht werden. Dieser Dienst läuft immer auf der momentanen Primary-Database und wird bei einem Switchover oder Failover mit umgezogen. Dieses Verhalten kann mit einem Trigger erreicht werden, den wir auf der Primary Datenbank anlegen und per Redo-Apply auf die Standby Datenbank übertragen.

Trigger erstellen

Der Trigger startet den Oracle Service immer dann, wenn die Datenbank PRIMARY ist.
CREATE OR REPLACE TRIGGER MARS_SERVICE AFTER STARTUP ON DATABASE
DECLARE
  v_role VARCHAR(30);
BEGIN
  SELECT DATABASE_ROLE INTO v_role FROM V$DATABASE;
  IF v_role = ‘PRIMARY’ THEN
    DBMS_SERVICE.START_SERVICE(‘marsdb’);
  END IF;
END;
/
Wenn die Standby Datenbank von Zeit zu Zeit mal im READ_ONLY Modus laufen soll oder wenn das Feature Active Dataguard lizenziert wurde, kann der Trigger erweitert werden. Der Trigger startet immer dann der Oracle Service marsro (für "mars read only"), wenn es die momentane Standby Datenbank ist, die gerade gestartet wird. Die Erweiterung des Triggers sieht so aus:
CREATE OR REPLACE TRIGGER MARS_SERVICE AFTER STARTUP ON DATABASE
DECLARE
  v_role VARCHAR(30);
BEGIN
  SELECT DATABASE_ROLE INTO v_role FROM V$DATABASE;
  IF v_role = ‘PRIMARY’ THEN
    DBMS_SERVICE.START_SERVICE(‘marsdb’);
  ELSE
    DBMS_SERVICE.STOP_SERVICE(‘marsro’);
  END IF;
END;
/
Also, wie funktioniert der Trigger?
Immer beim ALTER DATABASE OPEN [READ ONLY]; prüft der Trigger ob die Datenbank PRIMARY ist oder nicht. Wenn sie PRIMARY ist, dann wird der Service marsdb gestartet. Andernfalls (READ_ONLY mit oder ohne Apply) wird der Service marsro gestartet. So ist die offene Datenbank immer unter dem Service Name marsdb erreichbar und die Datenbank im READ_ONLY Modus immer über den Service marsro. Also völlig transparent wird der Client immer auf die richtige Datenbank geschickt.

Client Konfiguration

Im Client ist jetzt eine Spezielle Konfiguration erforderlich damit er beide Datenbank-Server kennt.
In der TNSNAMES.ora muss der folgende Eintrag erstellt werden:
marsdb =
(DESCRIPTION =
  (ADDRESS_LIST =
  (ADDRESS = (PROTOCOL = TCP)(HOST = primhost)(PORT = 1521))
  (ADDRESS = (PROTOCOL = TCP)(HOST = stbyhost)(PORT = 1521))
  (LOAD_BALANCE = no)
  (FAILOVER = yes)
  )
  (CONNECT_DATA =
    (SERVER = DEDICATED)
    (SERVICE_NAME = marsdb)
    (failover_mode =
      (type = select)
      (method = preconnect)
      (retries = 50)
      (delay = 5)
    )
  )
)
Für unsere Freunde aus dem Java-Umfeld noch der JDBC Connectionstring:
jdbc:oracle:thin:@(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = primhost)(PORT = 1521)) (ADDRESS = (PROTOCOL = TCP)(HOST = stbyhost)(PORT = 1521))(LOAD_BALANCE = no)(FAILOVER = yes))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = marsdb)(failover_mode = (type = select)(method = preconnect)(retries = 50)(delay = 5))))
Was wird hier dem Client mitgeteilt?
  • Es existieren 2 Datenbanken die wo der Service marsdb gefunden werden kann.
  • LOAD_BALANCE ist aus weil ja immer nur eine Datenbank offen ist.
  • FAILOVER ist an und zwar mit der folgenden Konfiguration:
    • PRECONNECT
    • 50x soll versucht werden ein Reconnect durchzuführen.
    • 5 Sekunden Abstand zwischen den Reconnects.
Diese Konfiguration eignet sich besonders für Umgebungen die einen Observer haben. Ansonsten kann der Teil "failover_mode" weggelassen werden, denn es muss sowieso ein Manueller Eingriff erfolgen.
Für den Dienst marsro muss natürlich aus so ein Eintrag erstellt werden.
That's IT