=====DBMS_SCHEDULER Job Log Lösch-Verhalten - Löschen optimieren===== **wohl ab min. 11g - getestet 12.2 und 18c/19c** ****Aufgabe:**** Der Oracle Scheduler loggt alle Läufe der Jobs in den Tabellen sys.scheduler$_event_log und sys.scheduler$_job_run_details. In einer Datenbank sind nun schon mehr als 4000 Tage an Log Informationen aufgelaufen. Warum also löscht der automatische Job der Datenbank diese Daten nicht? Aufgefallen ist der Fehler weil Abfragen auf die DBA Views für die Job Logs recht lange Laufzeiten (deutlich in 10sec Bereich) aufweisen. ****Lösung:**** Tägliche läuft im normal Fall ein Job mit **DBMS_SCHEDULER.PURGE_LOG()** der dieses Log aufräumt indem alles älter als der Parameter** LOG_HISTORY** ( auslesen mit DBA_SCHEDULER_GLOBAL_ATTRIBUTE ), im Default steht dieser Wert auf den Wert 30. Allerdings kann dieser Parameter auf JOB Klassen Ebene (DBA_SCHEDULER_JOB_CLASSES) pro Job Klasse überschrieben werden! Steht dieser Wert auf einen deutlichen höheren Default, werden diese Einträge dann eben nicht mehr mittelfristig gelöscht. D.h. die folgenden Punkte müssen überprüft werden: - Wie voll ist das Log? Wie alt sind die Daten - Ist der automatische Lösch-Job angelegt - wie ist die Rentention Period parametrisiert - Bei Bedarf Wert anpassen - Läuft der Job überhaupt regelmäßig - Überschreiben Definition auf Klassen Ebene die eigentliche gewünschten Einstellungen auf globale Ebene - Anpassen der Klassen Parameter - Manuell das Log löschen ---- ====Wie voll ist das Log? Wie alt sind die Daten==== Überprüfen mit: select count(*) as count_log , min(log_date) as first_log , max(log_date) as last_log , trunc(max(log_date)) -trunc(min(log_date)) as log_tage from dba_scheduler_job_log / COUNT_LOG FIRST_LOG LAST_LOG LOG_TAGE ------------ --------- ---------- ----------- 67538 04-NOV-16 01-SEP-20 1397 ---- ====Wie ist der automatische Lösch-Job parametrisiert==== select * from DBA_SCHEDULER_GLOBAL_ATTRIBUTE; ATTRIBUTE_NAME VALUE ------------------------------ -------------------- ... LOG_HISTORY 30 ... D.h. im Prinzip sollten nach 30 Tage alle Daten gelöscht werden (außer auf Klassen Ebene ist etwas anders definiert). === Parameter einstellen=== Wird weniger Log benötigt, den Zeitraum z.B. auf 10 Tage kleiner einstellen: sqlplus / as sysdba SYS@GPI> exec DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE('log_history','10'); PL/SQL procedure successfully completed. SYS@GPI>select VALUE from DBA_SCHEDULER_GLOBAL_ATTRIBUTE where ATTRIBUTE_NAME='LOG_HISTORY'; VALUE ------ 10 ---- ====Lösch Job überprüfen ==== select js.owner , js.job_name , decode (js.state, 'SCHEDULED', 'SHUD', 'DISABLED', 'DIS', 'RUNNING', 'RUN', js.state) as state , js.JOB_CLASS , js.program_name , js.job_action , to_char (o.CREATED, 'dd.mm.yyyy hh24:mi') as CREATED , js.run_count , js.failure_count , to_char (js.last_start_date, 'dd.mm hh24:mi') as last_start_date , to_char (js.next_run_date, 'dd.mm hh24:mi') as next_run_date from dba_scheduler_jobs js, dba_objects o where js.owner = o.owner(+) and js.job_name = o.OBJECT_NAME(+) and js.job_name like 'PURGE_LOG' order by owner, job_name / Was für Fehler liegen vor? select d.owner||'.'||d.job_name as job_name ,l.job_class ,d.log_date ,d.status ,d.error# error_number ,d.errors ,d.actual_start_date ,extract (second from d.cpu_used) + ( extract (minute from d.cpu_used) * 60) + ( extract (hour from d.cpu_used) * 60 * 60) as timeused ,l.additional_info from dba_scheduler_job_run_details d right join dba_scheduler_job_log l on (d.log_id = l.log_id) where d.job_name like 'PURGE_LOG' and d.status != 'SUCCEEDED' / Ist der Job zum Beispiel nicht aktiv, als SYS User aktiveren mit: execute dbms_scheduler.enable('PURGE_LOG'); ---- ====Überschreiben Definition auf Klassen Ebene die eigentliche gewünschten Einstellungen auf globale Ebene==== Überprüfen der Einstellungen der Job Klassen: select owner , job_class_name , logging_level , log_history , comments from DBA_SCHEDULER_JOB_CLASSES order by log_history / -------------------- OWNER ------------------------------------------------- JOB_CLASS_NAME ------------------------------------------------- LOGGING_LEVEL LOG_HISTORY --------------------------------- ------------ COMMENTS ------------------------------------------------- SYS ORA$AT_JCNRM_OS FULL 1000000 auto optimizer stats collection D.h. für die Auto Job Klassen ist als Default 1.000.000 Tage hinterlegt, d.h. in unsere Fall werden bereist schon am 30.07.4758 die Daten von heute gelöscht. Wohl etwas spät ... Setzen pro Klasse: sqlplus / as sysdba exec DBMS_SCHEDULER.SET_ATTRIBUTE('ORA$AT_JCNRM_OS','log_history','30'); -- -- Für alle erzeugen und dann das Spool ausführen select 'exec DBMS_SCHEDULER.SET_ATTRIBUTE('''||JOB_CLASS_NAME||''',''log_history'',''30'');' as command from DBA_SCHEDULER_JOB_CLASSES where nvl(LOG_HISTORY,0) > 30; COMMAND ------------------------------------------------------------------------------- exec DBMS_SCHEDULER.SET_ATTRIBUTE('ORA$AT_JCURG_OS','log_history','30'); ... ... -- -- Kommando kopieren und wieder in SQL*Plus ausführen -- SYS@GPI>exec DBMS_SCHEDULER.SET_ATTRIBUTE('ORA$AT_JCURG_OS','log_history','30'); PL/SQL procedure successfully completed. -- -- Überprüfen -- select JOB_CLASS_NAME , LOG_HISTORY from DBA_SCHEDULER_JOB_CLASSES / JOB_CLASS_NAME LOG_HISTORY -------------- ------------ ORA$AT_JCURG_OS 30 ... ---- ====Das Log manuell löschen==== === Hart alles löschen === Laut Support Node "How To Purge DBA_SCHEDULER_JOB_LOG and DBA_SCHEDULER_WINDOW_LOG (Doc ID 443364.1)" kann auch die folgende harte Methode verwendet werden: .. Truncate on these two tables is supported and can be done as .. truncate table sys.scheduler$_event_log; truncate table sys.scheduler$_job_run_details; === Selectiv löschen === Alles nach eingestellter Rentention Regel: exec DBMS_SCHEDULER.PURGE_LOG(); Alle älter als x Tage im Job Log löschen: exec DBMS_SCHEDULER.PURGE_LOG(7,which_log=>'JOB_LOG'); Alle älter als x Tage im Window Log löschen: exec DBMS_SCHEDULER.PURGE_LOG(7,which_log=>'WINDOW_LOG'); Prüfen ob es geklappt hat: select count(*) from dba_scheduler_window_log where log_date ---- ---- ==== Quellen ==== Oracle Support * How To Purge DBA_SCHEDULER_JOB_LOG and DBA_SCHEDULER_WINDOW_LOG (Doc ID 443364.1) * PURGE_LOG Job will purge all entries and ignore the setting of LOG_HISTORY (Doc ID 1270854.1)