24_39_214370_DOAG 03.05.2006 11:41 Uhr Seite 35 Jobketten Datenbank Jobketten in Oracle 10g R2 Autor: Christian Kutsch, MuniQSoft GmbH Mit Oracle 10g macht Oracle seinem altgedienten dbms_job-Package mit einem neuen, in die Datenbank integrierten Planungswerkzeug Konkurrenz im eigenen Hause. Das Werkzeug heißt “Scheduler” und ist seinem Vorgänger in mancher Hinsicht überlegen. Die Scheduler-Jobs sind nicht auf die Ausführung von PL/SQL-Code eingeschränkt. Es ist möglich, direkt Betriebssystem-Kommandos abzusetzen oder ab 10g Release 2 ganze Ketten von Jobs zu verwalten. Rückgriffe auf OSHilfsmittel wie zum Beispiel Unix-Cron sind nun nicht mehr erforderlich. Es ist sogar Event-gesteuertes Scheduling möglich. Bausteine der Planung Der Scheduler unterscheidet Jobs, Programme und Schedules. Das sind die Bausteine, aus denen die Job-Steuerung zusammengesetzt wird. Ein Schedule gibt der Zeitplanung einen Namen. Sie können beispielsweise einen Zeitplan mit dem Namen “StuendlichWerktags” erzeugen, der Montag bis Freitag jeweils in der Zeit zwischen 8 und 20 Uhr beliebige Ausführungszeitpunkte definiert. Ein Programm gibt einem ausführbaren Modul einen Namen, definiert den Typ des Moduls und wo es zu finden ist. Ein Job bildet die Verbindung zwischen Schedule und Programm. Obwohl die Aufteilung der Informationen in Programme, Schedules und Jobs als strukturierte Modularisierung empfohlen wird, ist es auch möglich, einen Job zu erzeugen, in dem bereits alle erforderlichen Informationen fest definiert sind. – Jobketten Mehrere voneinander abhängige Jobs lassen sich zu einer Jobkette verknüpfen. Eine Jobkette besteht aus Job, Chain, Steps und Rules. – Job Auf der obersten logischen Ebene wird ein Job vom Typ CHAIN erzeugt. Er enthält neben dem zu verwendenden Zeitplan den Namen der abzuarbeitenden Kette. – Step Ein Schritt definiert eine Einzel-Aktivität, gibt ihr einen Namen und ordnet ein Programm zu. – Rule Mit Regeln wird definiert, unter welchen Voraussetzungen die Schritte einer Kette auszuführen sind. Hier werden die gegenseitigen Abhängigkeiten beschrieben. Beispiel für den Aufbau einer Jobkette Bevor man mit der Definition der Elemente beginnt, muss man im Scheduler die Timezone korrekt einstellen. Außerdem werden dem Datenbank-User die benötigten Rechte erteilt. BEGIN dbms_scheduler.set_scheduler_attribute (attribute=>’default_timezone’, value=>’Europe/Berlin’); END; / grant create job to scott; grant create external job to scott; BEGIN DBMS_RULE_ADM.grant_system_privilege( Privilege=>DBMS_RULE_ADM.create_ rule_set_obj, grantee=>’SCOTT’, grant_option=>FALSE); DBMS_RULE_ADM.grant_system_privilege( privilege=>DBMS_RULE_ADM. create_evaluation_context_obj, grantee=>’SCOTT’, grant_option=>FALSE); DBMS_RULE_ADM.grant_system_privilege( privilege=>DBMS_RULE_ADM.create_ rule_obj, grantee=>’SCOTT’, grant_option=>FALSE); END; / – Schedule Ein Schedule ist ein Modul zur Ermittlung der Start-Zeitpunkte von Jobs und Jobketten. Oracle unterscheidet Time-based- und Event-based-Schedules. Time-based bedeutet, dass feste Start-Zeitpunkte definiert sind. Event-based bedeutet, dass die Start-Zeitpunkte dynamisch bei Eintreten bestimmter Ereignisse erzeugt werden. Ein Schedule wird als Zeitplan mit einem Job verknüpft. – Chain Die Kette fasst alle sequenziell auszuführenden Schritte zusammen. www.doag.org News Q2-2006 35 24_39_214370_DOAG 03.05.2006 Datenbank 11:41 Uhr Seite 36 Jobketten Als Datenbank-User SCOTT erzeugt man zunächst drei einfache PL/SQL-Prozeduren, aus denen später die Kette zusammengesetzt werden soll: CREATE TABLE chain_test1 (id number, text varchar2(40), datum date); CREATE OR REPLACE PROCEDURE test_proc1 IS BEGIN insert into chain_test1 values (1,’Test 1’,sysdate); commit; END; / CREATE OR REPLACE PROCEDURE test_proc2 IS BEGIN insert into chain_test1 values (2,’Test 2’,sysdate); commit; — raise predefined exception to illustrate — ERROR_CODE-Condition 1722 raise INVALID_NUMBER; END; / CREATE OR REPLACE PROCEDURE test_proc3 IS BEGIN insert into chain_test1 values (3,’Test 3’,sysdate); commit; END; / Die Namen dieser Prozeduren werden nun in Objekte des Typs Programm verpackt: BEGIN DBMS_SCHEDULER.create_program ( program_name => ‘chain_program_1’, program_type => ‘PLSQL_BLOCK’, program_action => ‘test_proc1;’, enabled => TRUE, comments => ‘Erstes Programm’); DBMS_SCHEDULER.create_program ( program_name => ‘chain_program_2’, program_type => ‘PLSQL_BLOCK’, program_action => ‘test_proc2;’, enabled => TRUE, comments => ‘Zweites Programm’); DBMS_SCHEDULER.create_program ( program_name => ‘chain_program_3’, program_type => ‘PLSQL_BLOCK’, program_action => ‘test_proc3;’, enabled => TRUE, comments => ‘Drittes Programm’); END; / 36 News Q2-2006 Im nächsten Schritt wird ein übergeordnetes Chain-Object erzeugt: BEGIN DBMS_SCHEDULER.CREATE_CHAIN ( chain_name => ‘chain1’, rule_set_name => NULL, evaluation_interval => NULL, comments => ‘Kette ‘); END; / Abschließend erfolgt die Definition der einzelnen Schritte mit Zuordnung der auszuführenden Programme: BEGIN DBMS_SCHEDULER.DEFINE_CHAIN_STEP ( chain_name => ‘chain1’, step_name => ‘step1’, program_name => ‘chain_program_1’); DBMS_SCHEDULER.DEFINE_CHAIN_STEP ( chain_name => ‘chain1’, step_name => ‘step2’, program_name => ‘chain_program_2’); DBMS_SCHEDULER.DEFINE_CHAIN_STEP ( chain_name => ‘chain1’, step_name => ‘step3’, program_name => ‘chain_program_3’); END; / Die Abhängigkeiten zwischen den Schritten werden über Regeln definiert: BEGIN DBMS_SCHEDULER.DEFINE_CHAIN_RULE ( chain_name => ‘chain1’, condition => ‘TRUE’, action => ‘START step1’, rule_name => ‘rule1’, comments => ‘Starte Kette 1’); DBMS_SCHEDULER.DEFINE_CHAIN_RULE ( chain_name => ‘chain1’, condition => ‘step1 SUCCEEDED’, action => ‘START step2’, rule_name => ‘rule2’); DBMS_SCHEDULER.DEFINE_CHAIN_RULE ( chain_name => ‘chain1’, condition => ‘step2 ERROR_CODE = 1722’, action => ‘START step3’, rule_name => ‘rule3’); DBMS_SCHEDULER.DEFINE_CHAIN_RULE ( chain_name => ‘chain1’, condition => ‘step3 COMPLETED’, action => ‘END’, rule_name => ‘rule4’, comments => ‘Ende der Kette’); END; / www.doag.org 24_39_214370_DOAG 03.05.2006 11:41 Uhr Seite 37 Jobketten Jede Regel besteht aus einer Bedingung (condition) und einer Aktion (action), besitzt einen Namen und gehört zu einer Jobkette. Die Bedingung ist entweder wahr (TRUE) oder falsch (FALSE). Sobald der Schedule eine Jobkette anstößt, werden die Bedingungen der enthaltenen Regeln ausgewertet. Das System löst dann alle Aktionen aus, deren Bedingungen wahr sind. Für die Formulierung der Bedingungen wurde eine eigene einfache Syntax definiert, die so genannte ChainCondition-Syntax. Weil es sich bei den Bedingungen um Boolesche Werte handelt, sind zunächst die Ausdrücke TRUE und FALSE zulässig. Außerdem kann der Status oder Error-Code eines beliebigen Schritts abgefragt werden. Dazu kombiniert man einfach den Schrittnamen mit einem Schritt-Status (SUCCEEDED, FAILED, STOPPED, COMPLETED) oder Error-Code (ERROR_CODE). Datenbank Die Tool-Innovation für Oracle® Forms Developer: Beispiel: condition => ‘step1 SUCCEEDED’ condition => ‘step3 COMPLETED’ Es ist auch möglich, direkt den Error-Code eines Schrittes abzufragen: condition => ‘step2 ERROR_CODE = 1722’ Zur Formulierung komplexerer Bedingungen lassen sich die beschriebenen Ausdrücke mit den booleschen Operatoren AND und OR kombinieren oder mit NOT negieren. Beispiel: condition => ‘step1 SUCCEEDED AND step3 COMPLETED’ Neben dieser Chain-Condition-Syntax ist auch eine SQLnahe Syntax zulässig, in der bestimmte Schritt-Attribute direkt abgefragt werden können. Beispiel: condition => ‘:step2.completed AND :step1.end_date > sysdate – 1/24’ Aktionen bestehen aus dem Keyword START oder STOP, gefolgt von einem Schrittnamen, oder aus dem Keyword END zum Beenden der Jobkette. Die Kette muss nun aktiviert werden: BEGIN DBMS_SCHEDULER.ENABLE (‘chain1’); END; / Neu: Weitere Informationen zu den Themen der DOAG News finden Sie unter http://email.doag.org/ www.doag.org e inklusiv l-Version ia r -T e e t g un r: 30-Ta ck. Jetzt e h -C s n Migratio ining.de www.im jform Testen Sie jetzt kostenlos die Trial-Version unseres Entwicklertools und entdecken Sie seine faszinierenden Möglichkeiten. Damit können Sie mit Highspeed eine unbegrenzte Anzahl an Modulen durchsuchen und vergleichen, egal ob Textobjekte, WhereKlauseln oder PL/SQL-Code. Oder neue Module erzeugen und vorhandene verändern, beliebig viele Masken neu generieren, oder PL/SQLCodes nach frei definierten Regeln formatieren. Darüber hinaus ermöglicht Ihnen die TrialVersion, eine Migrationsanalyse für die 6i/10g Umstellung durchzuführen. imining gmbh Berduxstraße 22 · D-81245 München Tel. +49 89/89 66 67-21 · Fax +49 89/89 66 67-23 www.imining.de News Q2-2006 37 24_39_214370_DOAG 03.05.2006 Datenbank 11:42 Uhr Seite 38 Jobketten Der Job ist das letzte Objekt unseres Beispiels und fasst das Gesamtwerk über die Kette, Schritte und Regeln zusammen. In Variante 1 verzichten wir auf ein Schedule-Objekt und geben die Zeitplanung direkt im Job an: Linux ist das der Benutzer “nobody”). Dies kann jedoch umkonfiguriert werden. Unter Windows muss erst der entsprechende Dienst mit der Bezeichnung OracleJobScheduler<SID> passend konfiguriert und gestartet werden. BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => ‘chain_job_1’, job_type => ‘CHAIN’, job_action => ‘chain1’, repeat_interval=>’freq=daily; byhour=14; byminute=30; bysecond=0’, enabled => TRUE); END; / Alternativ kann auch ein eigener Schedule erzeugt und im Job verwendet werden: BEGIN DBMS_SCHEDULER.CREATE_SCHEDULE ( schedule_name => ‘zeitplan’, repeat_interval=>’freq=daily; byhour=14; byminute=30; bysecond=0’); END; / BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => ‘chain_job_1’, job_type => ‘CHAIN’, job_action => ‘chain1’, schedule_name=>’zeitplan’, enabled => TRUE); END; / Ab sofort wird nun täglich um 14:30 Uhr die Verarbeitung der neuen Jobkette angestoßen. Falls das erste der drei Programme erfolgreich beendet werden kann, startet das zweite Programm. Das dritte Programm wird nur angestoßen, falls das zweite mit einer INVALID_NUMBER-Exception abbricht (der Error-Code hat den Wert 1722). Um statt der PL/SQL-Prozeduren ein BetriebssystemSkript (oder ein ausführbares Programm) zu verwenden, ist ein entsprechendes Programm-Modul hinzuzufügen: BEGIN DBMS_SCHEDULER.create_program ( program_name => ‘external_program_1’, program_type => ‘EXECUTABLE’, program_action=> ‘/opt/oracle/download/scott/extShell.sh’, enabled => TRUE, comments => ‘Shell-Skript’); END; / Der Exit-Status (SUCCEEDED, FAILED) eines Skripts lässt sich ebenfalls in der Jobkette auswerten. Hier gibt es jedoch eine Einschränkung. Es ist zwar möglich, zwischen Erfolg (returncode 0) und Fehlerfall (returncode <> 0) zu unterscheiden, detailliertere Abfragen auf den ERROR_CODE (wie oben beschrieben) sind jedoch für BetriebssystemSkripte und Programme bisher nicht möglich. Besser sieht es allerdings für PL/SQL-Prozeduren und Blöcke aus, deren Exceptions direkt in den Regel-Bedingungen abgefragt werden können (siehe Beispiel). Optional kann die Initialzündung einer Jobkette auch Event-getriggert über den AdvancedQueuing-Mechanismus der Datenbank erfolgen. Es ist möglich, einen eigens dafür vorgesehenen Schedule zu definieren, der einen Job oder eine Jobkette anwirft, sobald ein entsprechendes Ereignis eintritt. Auch dieser Schedule wird einfach über das Attribut schedule_name in den Job eingeklinkt. Data Dictionary Views Um den Status der definierten Module abzufragen, stellt Oracle eine Reihe von DataDictionary-Views zur Verfügung, die in der Oracle-Dokumentation ausführlich beschrieben werden und deshalb hier nur kurz erwähnt werden sollen: - USER_SCHEDULER_JOBS USER_SCHEDULER_SCHEDULES USER_SCHEDULER_PROGRAMS USER_SCHEDULER_CHAINS USER_SCHEDULER_CHAIN_STEPS USER_SCHEDULER_CHAIN_RULES Informationen über die tatsächlich ausgeführten Jobs mit allen verfügbaren Statis und Error-Codes sind in den folgenden Views zusammengefasst: - USER_SCHEDULER_JOB_LOG - USER_SCHEDULER_JOB_RUN_DETAILS Die Ausführung von OS-Programmen und Skripten erfolgt per default mit einem OS-User mit wenigen Rechten (unter 38 News Q2-2006 www.doag.org 24_39_214370_DOAG 03.05.2006 11:42 Uhr Seite 39 Jobketten SCHEDULE „zeitplan“ Datenbank JOB (Typ Chain) „chain_job_1“ CHAIN „chain_1“ Start succeeded CHAIN_STEP „step_1“ CHAIN_RULE „rule_1“ condition TRUE action Start CHAIN_STEP „step_2“ CHAIN_RULE „rule_2“ condition action error code Start CHAIN_STEP „step_3“ CHAIN_RULE „rule_3“ condition action completed CHAIN_RULE „rule_4“ condition action END PROGRAM „chain_program_1“ PROGRAM „chain_program_2“ PROGRAM „chain_program_3“ PL/SQL „test_proc_1“ PL/SQL „test_proc_2“ PL/SQL „test_proc_3“ Abbildung 1: Ablaufdiagramm des gezeigten Beispiels Benutzer mit ausreichenden Berechtigungen können über die entsprechenden ALL*- und DBA*-Views auch Jobketten anderer Benutzer abfragen. Fazit Für alle, die sich die erheblichen Ausgaben für ein professionelles Scheduling-System sparen wollen, bietet der Oracle-Scheduler eine leistungsfähige Alternative. Leider ist es in der aktuellen Version 10gR2 noch nicht möglich, den Exit-Status einzelner OS-Programme differenziert auszuwerten. Hier ist also noch Entwicklungspotenzial – ansonsten lässt der neue Scheduler kaum Wünsche offen. Alles vom DBMS_JOB-Package Gewohnte wird bei weitem übertroffen. Kontakt: Christian Kutsch [email protected] Neu: *IS MFJTUVOHTTUBSLFS %JFOTUMFJTUVOHTQBSUOFS GàS *OEJWJEVBMMÚTVOHFO BVG EFS #BTJT NPEFSOTUFS 0SBDMFVOE+"7"5FDIOPMPHJF &THFIUVN*IS5BHFTHFTDIÊGUVOE*ISF1SP[FTTF yVOELFOOFOEJFTFO8FCMPHOJDIU 4JFTJOE1SPm*OTJEFS XXXBNJTEFDPNCMPH NFISBMT)JUTJOEFOMFU[UFO.POBUFO ".*4%&654$)-"/%(.#) *OOVOHTUSBF )àSUI XXXBNJTEFDPN Artikel aus früheren Ausgaben der DOAG News finden Sie unter http://email.doag.org/ $PNJUUFEUP*$5*OWPMWFEJO1FPQMF www.doag.org News Q2-2006 39