Mittwoch, 7. August 2013

Authentifizierung bei APEX-Zugriff deaktivieren

Installiert man APEX mit PL/SQL Listener in einer Datenbank (außer XE), so muss man bei jedem Zugriff auf die APEX-Weboberfläche ein Username und Passwort eingeben. Es handelt sich hierbei um die Authentifizierung an der XML-Datenbank. Um dies abzustellen muss der folgende Code ausgeführt werden:

SET SERVEROUTPUT ON

DECLARE
  l_cfgxml XMLTYPE;
  l_value VARCHAR2(5) := 'true'; -- (true/false)
BEGIN
  l_cfgxml := DBMS_XDB.cfg_get();

  IF l_cfgxml.existsNode('/xdbconfig/sysconfig/protocolconfig/httpconfig/allow-repository-anonymous-access') = 0 THEN
    SELECT insertChildXML (
      l_cfgxml, '/xdbconfig/sysconfig/protocolconfig/httpconfig',
      'allow-repository-anonymous-access',
      XMLType('<allow-repository-anonymous-access xmlns="http://xmlns.oracle.com/xdb/xdbconfig.xsd">' ||
      l_value || '</allow-repository-anonymous-access>'),
      'xmlns="http://xmlns.oracle.com/xdb/xdbconfig.xsd"'
    ) INTO l_cfgxml FROM dual;

    DBMS_OUTPUT.put_line('Element inserted.');
  ELSE
    SELECT updateXML (
      DBMS_XDB.cfg_get(),
      '/xdbconfig/sysconfig/protocolconfig/httpconfig/allow-repository-anonymous-access/text()',
      l_value, 'xmlns="http://xmlns.oracle.com/xdb/xdbconfig.xsd"'
    )
    INTO l_cfgxml FROM dual;

    DBMS_OUTPUT.put_line('Element updated.');
  END IF;

  DBMS_XDB.cfg_update(l_cfgxml);
  DBMS_XDB.cfg_refresh;
END;
/


(Quelle: My Oracle Support)
That's IT

Mittwoch, 31. Juli 2013

APEX mit PL/SQL Embedded Gateway

Diese Konstellation ist nur für Umgebungen mit einer geringen Anzahl von Usern geeignet. Es empfielt sich immer einen Web-Server vor APEX zu hängen; Ich habe gute Erfahrungen mit Tomcat gemacht.
Zurück zum PL/SQL Embedded Gateway. Um eine akzeptable performance zu erreichen, sollte der Shared Server konfiguriert werden. Hier ein Beispiel für eine solche Konfiguration:

alter system set shared_servers=5;
alter system set max_shared_servers=20;
alter system set dispatchers='(PROTOCOL=TCP) (SERVICE=XE) (DISPATCHERS=3)';


Der SERVICE muss natürlich auf die entsprechende Umgebung angepasst werden.
That's IT.

Donnerstag, 18. Juli 2013

log_file_sync

Thank you Riyaj Shamsudeen for your good post on resolving log_file_sync wait events.
Here is the article: http://orainternals.wordpress.com/2008/07/07/tuning-log-file-sync-wait-events/

Donnerstag, 27. Juni 2013

"Execute to Parse"-Wert ist negativ

Bei einer Datenbank-Analyse fiel mir kürzlich auf, dass bei der Instanz-Effektivität des Statspack-Berichts (gilt auch für AWR) ein negativer Wert für Execute to Parse angegeben wurde. Zunächst bin ich einfach darüber hinweggegangen mit der Annahme, dass dies ein Erfassungsfehler oder sonst ein Bug im Bericht sei.
Instance Efficiency Indicators
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            Buffer Nowait %: 100.00       Redo NoWait %:  99.99
               Buffer Hit %:  99.99  Optimal W/A Exec %: 100.00
              Library Hit %:  93.59        Soft Parse %:  93.83
         Execute to Parse %: -43.82         Latch Hit %:  99.54
Parse CPU to Parse Elapsd %:  98.17     % Non-Parse CPU:  96.70
Was steckt jedoch wirklich hinter dieser negativen Zahl?
Die Anwendung, die diese Datenbank benutzt, hält nicht viel von Bind-Variablen. Deshalb war zu erwarten, dass dieser Wert gegen "0" geht. Ein negativer Wert bedeutet jedoch das Folgende:
Der Wert setzt sich zusammen aus [geparste SQLs]/[ausgeführte SQLs]*100. Normaler Weise sind die ausgeführten SQLs deutlich höher als die geparsten. Deshalb geht der Wert auch eher gegen 100% statt gegen 0%. In diesem Fall war aber die Anzahl der geparsten SQLs deutlich höher als die Anzahl der ausgeführten SQLs. Mit anderen Worten, die Anwendung lässt SQLs von der Datenbank parsen, die aber nie ausgeführt werden. Es werden hier also Datenbankressourcen verschwendet mit Operationen die niemand benötigt.
Was hier zu tun ist, liegt auf der Hand. Die Anwendung muss untersucht und bereinigt werden.

Update 2015-08-27:
Dieses Phänomen habe ich mittlerweile bei mehreren Datenbanken beobachtet. Wann immer die Entwickler der Anwendungen damit konfrontiert wurden, wurde dieses Verhalten der Anwendung vehement abgestritten. Meistens wird behauptet, dass SQLs nicht "prepared" werden und deshalb keine negative Zahl erscheinen kann. Es muss also mehr dahinter stecken als nur diese einfache Rechnung. Fakt ist, dass in der Datenbank etwas nicht ordnungsgemäß läuft.
Updates folgen...

Thrat's IT

Mittwoch, 26. Juni 2013

Mittwoch, 6. Februar 2013

Probleme beim Löschen einer Standby Datenbank

Diesen Blogeintrag liegt folgende Umgebung zu grunde:
Eine Oracle Datenbank vom Release 11.2.0.3 läuft auf einem Windows 2008 Server (das Betriebsystem spielt aber keine Rolle). Diese Datenbank hat 2 Standby-DBs die mit Oracle Dataguard Broker konfiguriert sind.
Eine der beiden Standby-Datenbanken sollte still gelegt werden was mit dem Befehl
DGMGRL> disable database "<DBUNIQUE_NAME>"
... normalerweise funktioniert.
Ein paar Tage später wurde die Standby-Datenbank dann komplett entfernt mit DGMGRL> remove database "<DBUNIQUE_NAME>". Zu dem Zeitpunkt war der Standby-Server nicht mehr verfügbar.
Kurze Zeit darauf fiel auf, dass im Enterprise Manager mehrere ARCH-Prozesse hohe Wartezeiten vom Typ "Unknown" haben. Im Alertlog konnten auch Timeouts beim Archivelog-Transport festgestellt werden. Ein Blick in das dazugeörige Tracefile machte dann deutlich, dass die stillgelegte Archivelog Destination Schuld an dem Problem trug. Anscheinend wird mit dem Broker-Befehl "disable database" bzw. "remove database" nur halbe Sache gemacht. Auch ein erneutes "enable configuration" half nichts. Oft ist das ja ein Heilmittel für solche Fälle.
Die Lösung war schlussendlich, die Archivelog-Destination von Hand mit
ALTER SYSTEM SET log_archive_dest_3='';
... zu löschen.
That's IT

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