Seiten

Posts mit dem Label dbms_scheduler werden angezeigt. Alle Posts anzeigen
Posts mit dem Label dbms_scheduler werden angezeigt. Alle Posts anzeigen

Dienstag, 8. Juli 2014

Statspack auf dem RAC

Wenn man das Statspack auf einem RAC benutzen will, kann es laut Jonathan Lewis dazu kommen, dass sich die einzelnen Instanzen beim Zugriff auf die DB gegenseitig locken.
"Now there’s no reason why Statspack should lock up a RAC cluster – in principle. But this was an 8-node cluster and if you set up the automatic job to take snapshots by running the default spauto.sql script all eight nodes could start running every hour on the hour – so they would all be fighting constantly for every block of every table and index in the Statspack schema.  (I’m exaggerating for effect, of course, but not by much). You might not notice the global cache contention in a 2-node cluster but eight nodes could, indeed, “lock up the system” at this point."
Sein Artikel bezieht sich zwar auf die 10g, aber es sieht so aus, als könnte es dieses Risiko in der 11g und höher weiterhin geben.
Auch ist RAC mit 2 Nodes wohl nicht gefährdet. Ich habe trotzdem ein wenig weiter gegraben. Hier http://www.oracle-class.com/?p=2384 ist ein guter Artikel, in dem beschrieben wird, wie man das Statspack auf einem 4-Node-RAC ausführen lässt. Die Anleitung bezieht sich ebenfalls auf Jonathan Lewis und nutzt sehr anschaulich DBMS_SCHEDULER und Services um die einzelnen Nodes gezielt anzusprechen.
Die Skripte lassen sich - geringfügig angepasst - so nutzen.

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.