Montag, 16. November 2015

"SET NEWNAME" per SQL generieren

Wer eine Datenbank clont und nicht die db_create_file_dest für alle DB-Files verwenden kann, muss unter umständen viele Datenbankfile manuell per "SET NEWNAME" anpassen.

Im Internet kursieren komischer Weise einige SQLs, die diesen Zweck nicht richtig erledigen. Vielleicht liegt es auch an inkompatiblen Befehlen. Dafür kenne ich mich mit den Änderungen im SQL-Bereich nicht gut genug aus.

In Oracle 11g muss das SQL jedenfalls so aussehen:

select 'set newname for datafile '||file_id||' to ''/PATH/TO/FILES/'||substr(file_name,instr(file_name,'/',-1)+1)||''';' 
  from dba_data_files
;
Oder mit v$-View:
select 'set newname for datafile '||file#||' to ''/PATH/TO/FILES/'||substr(name,instr(name,'/',-1)+1)||''';' 
  from v$datafile
;

That's IT

Mittwoch, 2. September 2015

Oracle Datenbanken mit RMAN verschieben

Es soll vorkommen, dass Datenbanken von einer Platte auf die andere verschoben werden sollen. Die folgende Beschreibung trifft ebenfalls zu, wenn die Datenbank vom Filesystem ins ASM oder andersherum verschoben wird.

Mit RMAN kann dies sehr gut vorbereitet werden um eine handliche Downtime von 10-20 Minuten zu erreichen. Mit etwas Einsatz kann auch eine 1-Minuten-Downtime erreicht werden.

Das folgende Beispiel entstand bei einem Umzug von ASM auf einem alten Storage ins Filesystem eines neuen Storage.

Schritt 1
Zunächst wird eine Image-Copy angelegt:
RMAN> backup incremental level 0 as copy database to destination '/opt/oracle/oradata' tag 'NEWSTORE';


Schritt 2
Die folgenden Pfade müssen im SPFILE angepasst werden. Dies kann online geschehen.
- db_create_file_dest
- FRA
- Archivelog-Dest
- Redologs

Schritt 3
Schritt 3 wird nun je nach Notwendigkeit zwischen der Vorbereitung und der Downtime 1-n Mal wiederholt. Dieser Vorgang aktualisiert die Image-Copy.
RMAN> backup incremental level 1 for recover of copy with tag 'NEWSTORE' database;
RMAN> recover copy of database with tag 'NEWSTORE';

Schritt 4 (switch)
Datenbank herunter fahren, Controlfiles verschieben und im SPFILE anpassen. Anschließend die Datenbank switchen:

Variante A (Alle Archivelogs seit dem letzten "Schritt 3" sind verfügbar):
RMAN> switch database to copy;
RMAN> recover database;

Variante B (Es sind nicht mehr alle Archivelogs verfügbar):
Zuerst "Schritt 3" ausführen, anschließend:
RMAN> switch database to copy;
RMAN> recover database;

Schritt 5
Datenbank wieder starten.

That's IT.

Montag, 6. Juli 2015

APEX 505 Fehler, I/O-Fehler: "Network Adapter could not establish the connection"

Problembeschreibung und Umgebung

Heute stieß ich auf den folgenden sonderbaren Fehler, den ich gerne teilen möchte. Eine APEX-Installation in einem Oracle Real Application Cluster (RAC) läuft auf einem Knoten plötzlich auf einen Fehler. Die Browser-Seite zeigte einen 505-Fehler.
Weitere Details zur Umgebung:
  • Oracle Version: 10g (2-Knoten RAC)
  • Oracle REST (APEX-Listener) 2.0.2
  • Applikations-Server: Tomcat

Symptome

Im catalina.out des Tomcat-Servers stand die folgende Fehlermeldung:
oracle.dbtools.common.jdbc.ConnectionPoolException: The pool named: apex is not correctly configured, error: I/O-Fehler: The Network Adapter could not establish the connection
         at oracle.dbtools.common.jdbc.ConnectionPoolException.badConfiguration(ConnectionPoolException.java:65)
         at oracle.dbtools.common.config.db.DatabaseConfig.badConfiguration(DatabaseConfig.java:166)
         at oracle.dbtools.common.config.db.DatabaseConfig.createPool(DatabaseConfig.java:187)
         at oracle.dbtools.common.config.db.DatabaseConfig.getConnection(DatabaseConfig.java:71)
         at oracle.dbtools.common.jdbc.ora.OraPrincipal.connection(OraPrincipal.java:69)
         at oracle.dbtools.apex.ModApexContext.getConnection(ModApexContext.java:372)
         at oracle.dbtools.apex.Procedure.getProcedure(Procedure.java:167)
         at oracle.dbtools.apex.OWA.validateProcedure(OWA.java:390)
         at oracle.dbtools.apex.security.Security.isValidRequest(Security.java:225)
 [...]
Wie gesagt, auf einem RAC-Knoten lief die Konfiguration, es gab keine Änderungen, die Konfigurationen waren auf beiden Knoten identisch.

Lösung

Die Apex-Dateien aus dem WEB-INF wurden gelöscht. Beim Neustart des Tomcats werden diese aus der .war-Datei automatisch neu deployed. Dieser erste Neustart wurde als tomcat-User manuell ausgeführt. Dabei durften die Umgebungsvariablen $LANG und $NLS_LANG nicht gesetzt sein!
$ su - tomcat
$ unset LANG
$ unset NLS_LANG
$ $CATALINA_HOME/bin/startup.sh
Anschließend war die APEX-Anwendung wieder über beide Knoten erreichbar.
Was genau das Problem war und wie es dazu kommen konnte, ließ sich anschließend natürlich kaum noch feststellen.
That's IT

Donnerstag, 8. Januar 2015

Oracle Upgrade: utlu112i.sql vergessen?

Wer kennt das nicht: Bei einem Upgrade möchte man das catupgrd.sql script laufen lassen, doch dieses läuft sofort auf den Fehler, dass irgend etwas mit der Tabelle registry$database nicht stimmt.
Das bedeutet man hat vor dem Upgrade das utlu112i.sql nicht ausgeführt. Entweder hat man es schlicht vergessen oder die Datenbank kommt aus einem Backup und man hatte überhaupt nicht die Möglichkeit das Script auszuführen.
In diesen Fällen muss man nicht unbedingt das utlu*i.sql Script vorher laufen lassen, es gibt auch eine einfache Korrektur.
Zunächst überprüft man die Tabelle registry$database:

SELECT TO_NUMBER('MUST_BE_SAME_TIMEZONE_FILE_VERSION')
FROM registry$database
WHERE tz_version != (SELECT version from v$timezone_file);

Wenn die Tabelle registry$database nicht existiert (für 11gR2):

CREATE TABLE registry$database (
 PLATFORM_ID    NUMBER,
 PLATFORM_NAME  VARCHAR2(101),
 EDITION        VARCHAR2(30),
 TZ_VERSION     NUMBER
);

Wenn die Tabelle registry$database existiert (für11gR2):

alter table registry$database add (tz_version number);
delete from registry$database;


Für beide Varianten muss noch folgendes ausgeführt werden:

INSERT into registry$database
       (platform_id, platform_name, edition, tz_version)
VALUES ((select platform_id from v$database),
        (select platform_name from v$database),
        NULL,
        (select version from v$timezone_file));
commit;


That's IT