Seiten

Sonntag, 30. Dezember 2012

Es sich als Oracle-DBA auf einem Windowsserver gemütlich machen

Nach einer Standardinstallation der Oracle Datenbankksoftware auf einem Windowsserver sollte man folgende Anpassungen vornehmen, ohne die zwar auch arbeiten kann, das aber nicht sonderlich komfortabel.

Schnellstartleiste

in der Schnellstartleiste sollten sich diese Einträge befinden:
  1. Windows Explorer
  2. Services
  3. Server Manager
  4. Scheduler
Das alles braucht man häufig, wenn man die Oracle-DB auf dem Server administrieren muss.

Desktop

Auf dem Desktop lege ich verschiedene Verknüpfungen an, die ebenfalls häufig benötigt werden, welche in der Schnellstartleiste aber sehr schnell für Chaos sorgen würden.
Die Commandshell benötigt man natürlich oft und das auch noch mit unterschiedlichen Umgebungsvariablen je nachdem, mit welcher Datenbank oder unter welchem ORACLE_HOME man arbeiten möchte.
In einer frischen RAC-Installation hat man es sofort mit 2 ORACLE_HOME-Directories (Grid und DB), sowie 2 Instanzen (ASM und z.B. ORCL) zu tun.
Natürlich "weiß" CMD nicht, welche Umgebung man gerade braucht. Zu allem Überfluss gelten die Standard-Pfade bzw. das ORACLE_HOME der zeitlich zuletzt ausgeführten Oracle-Installation. Auf das Grid_Home hat man also keinen Zugriff ohne die Umgebung immer manuell zu modifizieren.

oraenv?

Unter Linux ist das Dank oraenv-Skript kein Problem. Unter Windows gibt es aus unerfindlichen Gründen kein oranev.
Es gibt eine Reihe von Anleitungen, sich das fehlende oraenv-Skript selbst zu erstellen. Eine entsprechende Lösung findet man nach kurzem googlen.

Command-Shell-Batches - oraenv für Arme

Die in einer RAC-Installation benötigten Aufrufe der CMD oder von SQLPLUS konfiguriert man sich mit einfachen Batchdateien, die auf dem Desktop als Verknüpfung abgelegt werden. In einer "normalen" - also einer Single-Instance-Installation ohne ASM benötigt man nur 2 dieser Batchdateien.
Unter zum Beispiel d:\skripte\oraenvbat\ werden also diese Batchdateien auf den jeweiligen Knoten angelegt:
  • cmd_grid1.bat
  • cmd_RACDB1.bat
  • sys_RACDB1.bat
  • asmcmd1.bat
  • sys_asm1.bat
Natürlich muss man diese dann auf jedem RAC-Knoten anlegen und die "1" durch den korrekten Wert ersetzen.

GRID shell - cmd_grid1.bat

In der cmd_grid1.bat wird die Umgebung für das GRID-Home und die ASM-Instanz gesetzt.
Hier zeigt die ORACLE_SID auf die "+ASM1"-Instanz. Die "1" steht dabei für die Instanz auf Node1 des RAC.
@echo off
SET ORACLE_SID=+ASM1
set SQLPATH=D:\skripte\oraenvbat
SET ORACLE_HOME=D:\oragrid\11.2.0.3
SET PATH=%ORACLE_HOME%\bin;%PATH%
set NLS_LANG=GERMAN_GERMANY.WE8PC850
%comspec%
pause

DB shell - cmd_RACDB1.bat

Die cmd_RACDB1.bat setzt ORACLE_SID der Instanz des RAC-Knotens (RACDB1), ORACLE_UNQNAME und Oracle-Home der Datenbank.
@echo off
SET ORACLE_SID=RACDB1
SET ORACLE_UNQNAME=RACDB
set SQLPATH=D:\skripte\oraenvbat
SET ORACLE_HOME=D:\oracle\product\11.2.0.3\dbhome_1
SET PATH=%ORACLE_HOME%\bin;%PATH%
set NLS_LANG=GERMAN_GERMANY.WE8PC850
%comspec%
pause

sqlplus auf die DB as sysdba - sys_RACDB1.bat

Es ist recht bequem, sich per Doppelklick auf die sys_RACDB1.bat als SYSDBA mit der DB  zu connecten. Und noch besser: hiermit kommt man auch noch auf Instanz des jeweiligen RAC-Knotens. (RACDB1)
@echo off
SET ORACLE_SID=RACDB1
set SQLPATH=D:\skripte\oraenvbat
SET ORACLE_HOME=D:\oracle\product\11.2.0.3\dbhome_1
SET PATH=%ORACLE_HOME%\bin;%PATH%
set NLS_LANG=GERMAN_GERMANY.WE8PC850
%ORACLE_HOME%\bin\sqlplus / as sysdba
pause

ASMCMD - asmcmd1.bat

Mit dieser Batchdatei startet man gleich ASMCMD.
@echo off
SET ORACLE_SID=+ASM1
set SQLPATH=D:\skripte\oraenvbat
SET ORACLE_HOME=D:\oragrid\11.2.0.3
SET PATH=%ORACLE_HOME%\bin;%PATH%
set NLS_LANG=GERMAN_GERMANY.WE8PC850
%ORACLE_HOME%\bin\asmcmd -p
pause

sqlplus auf die ASM as sysdba - sys_asm1.bat

Was man an Bequemlichkeit mit der sys_RACDB1.bat gewinnt, möchte man natürlich auch im Fall eines ASM-Connect haben.
@echo off
SET ORACLE_SID=+ASM1
set SQLPATH=D:\skripte\oraenvbat
SET ORACLE_HOME=D:\oragrid\11.2.0.3
SET PATH=%ORACLE_HOME%\bin;%PATH%
set NLS_LANG=GERMAN_GERMANY.WE8PC850
%ORACLE_HOME%\bin\sqlplus / as sysasm
pause
Mit diesen Batchdateien kommt man auf einem Windowssystem dann auch ohne oraenv gut über die Runden.

Dienstag, 25. Dezember 2012

Jobs in einer RAC-Installation an einen bestimmten Knoten binden

Es ist eigentlich ganz einfach, Jobs an einen bestimmten RAC-Knoten zu binden. Das einzige was man benötigt ist ein entsprechend konfigurierter Service und eine an diesen gebundene Job-Klasse.
Dem oder den Jobs weist man dann nur noch die Job-Klasse zu.
Fertig.

1. Service anlegen

Services legt man mit  dem DBCA oder srvctl an. Ich bevorzuge srvctl:
# Service auf einem Knoten anlegen 
srvctl add service -d RACDB -s JOB_SERVICE -r "RACDB1"

# Starten und stoppen des Service
srvctl start service -d RACDB -s JOB_SERVICE 
srvctl stop service -d RACDB -s JOB_SERVICE

# Disablen and enablen von Services.
srvctl disable service -d RACDB -s JOB_SERVICE
srvctl enable service -d RACDB -s JOB_SERVICE

# Möchte man den Service entfernen, dann mit remove:
srvctl remove service -d RACDB -s JOB_SERVICE

# Der Servicestatus:
srvctl status service -d RACDB -s JOB_SERVICE -v
Unter bestimmten Umständen zickt srvctl beim anlegen von Services. Beinhaltet die Domain der DB zum Beispiel ein "-" (minus), dann bemeckert srvctl das mit einem nichtssagenden PRCD-1223:
srvctl add service -d RACDB -s JOB_SERVICE -r "RACDB1"
PRCD-1223 : Der Servicename JOB_SERVICE enthält unzulässige Zeichen -
Abhilfe schafft die Umbenennung der Domain in der DB. Angenommen die Domain lautet "meinefirma-deutschland.de", macht man aus dem "-" einfach einen Punkt, oder was einem sonst gefällt.
srvctl modify database -m meinefirma.deutschland.de -d RACDB
Anschließend legt man den Service an und benennt die Domain wieder um.
srvctl add service -d RACDB -s JOB_SERVICE -r "RACDB1"
srvctl modify database -m meinefirma-deutschland.de -d RACDB

2. Job-Class anlegen

BEGIN
  DBMS_SCHEDULER.create_job_class (
    job_class_name => 'NODE1_JOB_CLASS',
    service        => 'JOB_SERVICE');
END;
/

3. Jobs eine Job-Klasse zuweisen

Jetzt kann man neue Jobs direkt einer Job-Klasse zuweisen oder existierende Jobs entsprechend ändern

3.a) Einen neuen Job mit Jobklasse anlegen

Beim anlegen eines Jobs kann man ihm mit dem Parameter JOB_CLASS gleich die Job-Klasse zuweisen.
Ohne Verwendung dieses Parameters, erfolgt die Zuweisung des Defaultwertes:
BEGIN
  DBMS_SCHEDULER.create_job (
    job_name        => 'TEST_JOB',
    job_type        => 'PLSQL_BLOCK',
    job_action      => 'BEGIN ... END;',
    job_class       => 'NODE1_JOB_CLASS',
    repeat_interval => 'FREQ=DAILY',
    enabled         => TRUE,
    comments        => 'Job mit Zuordnung zu einer Job-Klasse');
END;
/

3.b) Zuordnung einer Job-Klasse zu einem existierenden Job

Einfach:
BEGIN
  DBMS_SCHEDULER.set_attribute (
    name      => 'TEST_JOB',
    attribute => 'job_class',
    value     => 'NODE1_JOB_CLASS');
END;
/

4. Sonstiges

Jobs abfragen

SELECT owner, job_name, job_class, enabled 
FROM dba_scheduler_jobs;

Test: Führt der RAC den Job tatsächlich nur auf Node1 aus?

Wenn man testen möchte, ob die Servicezuweisung wirklich funktioniert, kann man wie folgt vorgehen.
Man legt per CTAS eine Testtabelle an:
CREATe TABLE job_test AS 
SELECT sysdate time, instance_name, host_name 
FROM v$instance;
Dann legt man einen Job an, der sekündlich sysdate, den Instanz- und Hostnamen in die Testtabelle schreibt:
BEGIN
  DBMS_SCHEDULER.create_job (
    job_name        => 'TEST_JOB',
    job_type        => 'PLSQL_BLOCK',
    job_action      => 'INSERT INTO job_test SELECT sysdate time, instance_name, host_name FROM v$instance;commit;',
    job_class       => 'NODE1_JOB_CLASS',
    start_date      => TO_TIMESTAMP_TZ('02/01/2012 13:45:00','dd/mm/yyyy hh24:mi:ss'),
    repeat_interval => 'FREQ=SECONDLY',
    end_date        => TO_TIMESTAMP_TZ('02/01/2013 14:00:00','dd/mm/yyyy hh24:mi:ss'),
    enabled         => TRUE,
    comments        => 'Job mit Zuordnung zu einer Job-Klasse');
END;
/
Die Abfrage zur Überprüfung sollte dann natürlich nur die eine beteiligte Instanz hervorzaubern:
SELECT * FROM job_test ORDER BY 1 DESC;

Was passiert, wenn der Service gedropt wird?

Wenn ein Service gelöscht wird, auf den Job-Klassen verweisen, wird automatisch die Default-Job-klasse gezogen.

Beispiel für die Nutzung von Services

Auf einer Oracle-RAC-DB mit 4 Knoten laufen eine Client-Server-Anwendung, ein Webportal und mehrere über Webservices realisierte Schnittstellen zu anderen Anwendungen.
Die Anforderungen der 3 auf die DB zugreifenden Systeme unterscheiden sich stark und sollen voneinander getrennt und optimiert arbeiten. 
# 3 Services anlegen
srvctl add service -d RACDB -s CLIENT_SERVICE -r RACDB1 -a "RACDB1,RACDB4"
srvctl add service -d RACDB -s WWW_SERVICE -r RACDB2,RACDB3 -a "RACDB2,RACDB3,RACDB4"
srvctl add service -d RACDB -s BATCH_SERVICE -r RACDB4 -a "RACDB1,RACDB4"
Jetzt müssen die Clients, das Webportal und die Web-/Batchservices nur noch entsprechend auf die Services zugreifen.
Das konfiguriert man z.B. in den jeweiligen tnsnames.ora.
Der Clientservice kann dann auf allen 4 Knoten, wird aber bevorzugt auf dem 1er laufen.
Das Webportal wird bevorzugt auf 2 und 3 ausgeführt, kennt aber außerdem noch den 4er.
Die Schnittstellen laufen wiederum auf dem 4er und notfalls dem 1er.

Samstag, 22. Dezember 2012

dbms_scheduler mit EXECUTABLE unter Windows

Will man unter Windows datenbankgesteuert regelmäßig Dateioperationen im Netzwerk ausführen, muss man einige Hürden überwinden.
An diesem Beispiel beschreibe ich die notwendigen Schritte:
Aus der Oracledatenbank (11.2.0.3) wird täglich um 20:00Uhr eine Batchdatei (d:\skripte\backup.bat) gestartet, die eine Datei inkl. Tagesdatum ins Firmennetz sichern soll.

Der Inhalt der backup.bat:
set jahr=%date:~-4%
set monat=%date:~-7,2%
set tag=%date:~-10,2%

copy D:\oradata\orcl\backup.zip \\192.168.2.100\bckp\%jahr%%monat%%tag%_backup.zip
Das Skript um den Scheduler-Job zu erzeugen, sieht so aus:
BEGIN
  DBMS_SCHEDULER.CREATE_JOB(
    job_name         => 'JOB_COPY_BACKUP'
    ,repeat_interval => 'FREQ=DAILY;BYHOUR=20'
    ,job_class       => 'DEFAULT_JOB_CLASS'
    ,job_type        => 'EXECUTABLE'
    ,NUMBER_OF_ARGUMENTS => 2
    ,job_action      => 'c:\windows\system32\cmd.exe'
    ,comments        => 'Job startet das Backup.'
    );
END;
/
Das Grundgerüst steht damit. Weil man die Batchdatei nicht direkt aufrufen kann, muss man sie als Argument an die Commandshell inkl. Schalter "/C" übergeben. Das sähe dann in etwa so aus: "c:\windows\system32\cmd.exe /c d:\skripte\backup.bat > nul"
Diese Argumente setzt man mit DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE(). Das Logging setzt man mit DBMS_SCHEDULER.SET_ATTRIBUTE. Diese Loglevel gibt es:
  • DBMS_SCHEDULER.LOGGING_OFF,
  • DBMS_SCHEDULER.LOGGING_RUNS,
  • DBMS_SCHEDULER.LOGGING_FULL
Wenn man AUTO_DROP auf FALSE setzt, verhindert man, dass der Job nach der letzten Ausführung aus der DB verschwindet.
Zuletzt muss der Job enabled werden. Standardmäßig sind die Jobs disabled und werden damit nicht ausgeführt.
BEGIN
  DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE('JOB_COPY_BACKUP',1,'/c');
  DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE(
    'JOB_COPY_BACKUP',2,'d:\skripte\backup.bat > nul');
  DBMS_SCHEDULER.SET_ATTRIBUTE(
    name       => 'JOB_COPY_BACKUP'
    ,attribute => 'LOGGING_LEVEL'
    ,value     => DBMS_SCHEDULER.LOGGING_RUNS);
  DBMS_SCHEDULER.SET_ATTRIBUTE( 
    name       => 'JOB_COPY_BACKUP'
    ,attribute => 'AUTO_DROP'
    ,value     => FALSE);
  DBMS_SCHEDULER.ENABLE('JOB_COPY_BACKUP');
END;
/
Bei einem "normalen" Job ohne Netzwerkugriff wäre man jetzt fertig. In diesem Fall würde der Job in einer  Fehlermeldung enden.
Was ist zu beachten? Der Prozess, der die Batchdatei startet, muss unter einem Konto laufen, dass Schreibrechte ins Netz hat.
Nach einer Standardinstallation werden die Windowsdienste unter dem Systemkonto (Local System) ausgeführt. Der Schedulerservice selbst ist sogar disabled:
















Den Service muss man enablen und einem Konto zuweisen, das Schreibrechte ins Netzwerk besitzt - hier ora_dba:

Jetzt sollte der Job wie erwartet funktionieren. Das Log kann man mit diesem Select abrufen:
select * from dba_scheduler_job_log
where job_name = 'JOB_COPY_BACKUP'
Was gibt es sonst noch?
  • Man kann Jobs auch über "credentials" mit Username und Passwort starten. Das habe ich noch nicht ausprobiert.
  • Wenn man einen "EXECUTABLE-Job" in einer RAC-Umgebung anlegt, gibt es das Problem, dass der Scheduler-Job auf jedem Knoten ausgeführt werden kann. Dann muss man entweder dafür sorgen, dass die Files (Programme, Batch-Dateien...), auch tatsächlich für jeden Knoten auffindbar sind - Oder: Man sorgt dafür, dass der Scheduler-Job nur auf einem bestimmten Knoten läuft. Dazu später. (Stichwort: job_class)
  • Möchte man über Probleme oder auch nur die reine Jobausführung per Email benachrichtigt werden, kann man sich seit 11g bequem per eingebauter "email_notification" benachrichtigen lassen.
  • Außerdem bietet das Scheduler-Package auch die Möglichkeit, per Window die Ausführungszeiten zu steuern.

Samstag, 15. Dezember 2012

SQLPLUS - Komfort durch glogin.sql

Bei jedem Verbindungsaufbau mit einer Datenbank führt sqlplus die Datei glogin.sql (ORACLE_HOME\sqlplus\admin\glogin.sql) aus.
In der glogin.sql kann man damit zentral bestimmte Befehle/Einstellungen definieren, die einem die Handhabung erleichtern.

SQLPROMPT:
  • Datum: _date
  • eingeloggter User: _user
  • Privilege: _privilege
  • Datenbank _connect_identifier 
Damit ist schon einmal gewährleistet, dass man immer sieht, ob man als SYS eingeloggt ist. Das Datum kann auch nie schaden.
Weiterhin lassen sich Editor, Spaltenformate usw. definieren.
SQL-Befehle wie "ALTER SESSION..." lassen sich absetzen.

Hier als Beispiel meine Einstellungen:
set feedback off
set linesize 150
set pagesize 2000
set sqlprompt "_date _user _privilege'@'_connect_identifier>"
alter session set nls_date_format='dd.mm.yyyy hh24:mi:ss';
define _editor=c:\Windows\System32\notepad.exe
set serveroutput on size unlimited format wrapped
set long 1000000
set timing on
set feedback on
Das Ergebnis:
Update:
Nach dem Hinweis von Martin Preiss, habe ich das login etwas angepasst.
set feedback off
set linesize 150
set pagesize 2000
alter session set nls_date_format='dd.mm.yyyy hh24:mi:ss';
define _editor=c:\Windows\System32\notepad.exe
set serveroutput on size unlimited format wrapped
set long 1000000
set timing on
--set sqlprompt "_date _user _privilege'@'_connect_identifier>"
col global_name for a50
define gname=idle 
column global_name new_value gname 
select lower(user) || '@' || 
  substr(global_name,1,decode(dot,0,length(global_name),dot-1))
  || ' '  || sysdate  global_name
  from (select global_name,instr(global_name,'.') dot from global_name);
host title &gname 
set feedback on
Da die Logindaten in die Titelzeile wandern, verhindert man so die hässliche Promptverlängerung.

Die passende Doku:

Donnerstag, 13. Dezember 2012

Oracle-Linkliste

Meine persönlichen Favoriten/wichtigsten Seiten hinsichtlich Oracle

Infos und HowTo

Da hätten wir zum Beispiel die Oracle-Dojo-Reihe.

Der Begriff Dojo kommt aus dem japanischen Kampfsport und bedeutet übersetzt Übungshalle oder Übungsraum. Übungsräume sollen auch die Oracle Dojos sein. Sie sollen dazu dienen, sowohl Theorie als auch Praxis zu vermitteln. Das Ziel ist dabei immer die Verbesserung und Vertiefung der eigenen Fähigkeiten. “ Alles klar? http://www.oracle.com/webfolder/technetwork/de/community/dojo/index.html

RAC

RACCheck Tool - Best Practices http://www.oracle.com/webfolder/technetwork/de/community/dbadmin/tipps/raccheck/index.html
RAC-Tuning http://www.held-informatik.de/tipps-tricks/oracle-rac/oracle-rac-tuning.html

Backup&Recovery

...

Performance

nette Mindmap http://www.mindmeister.com/de/43617640/oracle-performance-tuning

Webservices

UTL_HTTP http://psoug.org/reference/utl_http.html
XML DB FAQ https://forums.oracle.com/forums/thread.jspa?threadID=410714&tstart=0
Im praktischer Einsatz http://www.theserverside.de/oracle-webservices-im-praktischen-einsatz/

Apex

Doku http://www.oracle.com/technetwork/developer-tools/apex/documentation/index.html

Software

Insider http://www.fourthelephant.com/insider/