Cambiar next_run_date en DBMS_SCHEDULER

Este atributo no se puede cambiar directamente, lo que se tiene que hacer es cambiar el start_date

exec dbms_scheduler.disable (‘<usuario>.<nombre_job>’);

declare
v_new_next_date timestamp with time zone;
begin
select to_timestamp_tz(to_char(trunc(sysdate),’DD-MON-YYYY’) || ‘ 12:05:00 PM +00:00′) into v_new_next_date
from dual;
dbms_scheduler.set_attribute(name=>'<usuario>.<nombre_job>’, attribute=>’START_DATE’,value=>v_new_next_date);
end;
/
EXEC dbms_scheduler.enable ( ‘<usuario>.<nombre_job>’);

/

Error ORA-12012: error on auto execute of job 4002

Bug que afecta de la 11.1.0.7 a la 11.2.02

Aparecen en el alert errores de jobs

 Errors in file /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_j000_10012.trc:
 ORA-12012: error on auto execute of job 4002
 ORA-01878: specified field not found in datetime or interval

 Estos errores se producen el cambio de horario, cuando se adelanta una hora-

Comprueba que la next_date de ejecución del job no se ha actualizado utilizando la siguiente select:

select job ,to_char(LAST_DATE,'YYYYMMDD HH24:MI:SS'),to_char( NEXT_DATE ,'YYYYMMDD HH24:MI:SS') from job$ where NEXT_DATE < sysdate;

La causa de este error es el Bug 11900845

No hay parche y el work auround consiste en actualizar el next_date:
Obtener el identificados del job y el usuario que tiene privilegios sobre él

SQL>select job, what, log_user, priv_user from dba_jobs where job=<job_number> ;

Connectarse como el usuario priv_user y actualizar el next_date con el valor correcto.

SQL>Exec DBMS_JOB.NEXT_DATE(--job--, to_date( -- correct time for execution-- ,'YYYYMMDD HH24:MI:SS');
SQL>Commit;

Como ejecutar un job en una instacia en concreto del RAC

Aquí pongo como ejecutar un job en una instancia en concreto del cluster. Si la instancia sobre la que se pide que se ejecute el job no está funcionando el job no se ejecuta.

DBMS_SCHEDULER.create_job

(job_name             => ‘FLUSH02_J’,

job_class            => ‘DEFAULT_JOB_CLASS’,

job_type             => ‘plsql_block’,

job_action           =>    ‘begin execute immediate(‘

|| »»

|| ‘alter system flush shared_pool’

|| »»

|| ‘); end;’,

repeat_interval      => v_repeat_interval

);

DBMS_SCHEDULER.set_attribute (NAME           => ‘FLUSH02_J’,

ATTRIBUTE      => ‘instance_id’,

VALUE          => 2

);

DBMS_SCHEDULER.ENABLE (‘FLUSH02_J’);

Oracle Scheduler

Oracle Scheduler es un herramienta que permite aejecutar trabajos de manera periódica autmomáticamente.

Crear un trabajo:

Se utiliza el procedimiento create_job

Aquí tenemos un ejemplo de un job que llama a un procedimiento externo. Este job asume que existe un ejecutable, /users/oracle/scripts/delete_logs.sh, que se encargará de borrar los logs antiguos

BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'DELETE_LOGS',
job_type => 'EXECUTABLE',
job_action => '/users/oracle/scripts/delete_logs.sh ',
repeat_interval => 'FREQ=DAILY;BYHOUR=14;BYMINUTE=11',
job_class => '"DEFAULT_JOB_CLASS"',
auto_drop => FALSE,
comments => 'Delete old files',
enabled => TRUE);
END;
/

Vamos a explicar algunos de los parámetros:

JOB_TYPE: Puede ser de los siguiente tipos: PROCEDURE, PLSQL_BLOCK oEXTERNA

REPEAT_INTERVAL : En este caso FREQ=DAILY;BYHOUR=14;BYMINUTE=11. En este caso todos los días las 2:11 p.m La sintaxis de este parámetro es bastante compleja, se pueden encontrar múltiples ejemplos en  The Oracle Database PL/SQL Packages and Types Reference guide

JOB_CLASS Normalmente se utliza para proporcionar un método de los jobs automáticamente hereden  atributos de esa clase. En este caso hemos utilizado la de por defecto.

AUTO_DROP Este parámetro le indica a oracle que no borre el job  después de ejecutarlo

Como ver los detalles del job

Para ver cómo está configurado se utiliza la vista DBA_SCHEDULER_JOBS

SELECT
  job_name
 ,last_start_date
 ,last_run_duration
 ,next_run_date
 ,repeat_interval
FROM dba_scheduler_jobs
WHERE job_name='<nombre_job>';

Cada vez que el job se jecuta se guarda un registro en DBA_SCHEDULER_JOB_LOG.

SELECT
 job_name
,log_date
,operation
,status
FROM dba_scheduler_job_log
WHERE job_name='<nombre_job>';

Cómo modificar el periodo de retención de un log

Por defecto Oracle Scheduler guarda 30 días del historio se puede moficiar de la siguiente manera:

SQL> exec dbms_scheduler.set_scheduler_attribute('log_history',15);

Para limpiar todo el histórico del job:

SQL> exec dbms_scheduler.purge_log();

Modificar un job:

Se puede modificar los atributos de un job mediate el procedimiento SET_ATTRIBUTE. Un ejemplillo

BEGIN
  dbms_scheduler.set_attribute(
    name=>'<nombre_job>'
   ,attribute=>'repeat_interval'
   ,value=>'freq=weekly; byday=mon');
END;
/

Parar un job:

SQL> exec dbms_scheduler.stop_job(job_name=>'<nombre_job>');

Habilitarlo o  deshabilitarlo:

exec dbms_scheduler.disable('DELETE_LOGS');
exec dbms_scheduler.enable('DELETE_LOGS');

Borrarlo:

exec dbms_scheduler.drop_job('DELETE_LOGS');

Como borrar jobs duplicados

Hace unos días nos encontramos que unos imports que habíamos hecho sobre la base de datos, duplicaron unos jobs, este es el procedimiento que utilizamos para borrar los jobs duplicados:

DECLARE
   CURSOR c2
   IS
      SELECT job
        FROM user_jobs
       WHERE ROWID NOT IN (SELECT   MIN (ROWID)
                               FROM user_jobs
                           GROUP BY what);
BEGIN
   FOR c IN c2
   LOOP
      DBMS_JOB.remove (c.job);
   END LOOP;
END;
/

Que hace el proceso CJQ0?

 CJQ0 es el coordinador procesos de cola de jobs.

 El proceso de cola de jobs ejecuta los jobs a medida que son asignados por el proceso CJQ.

Esto es lo que pasa:

1.  El coordinador del proceso, CJQ0, periódicamente selecciona los jobs que necesita que corran el desde la table de sistema JOB$. Los nuevos jobs incorporados se ordenen por tiempo.

2.  El proceso CJQ0 dinámicamente expande procesos esclavos de la cola de jobs (J000…J999) para ejecutar los jobs.

3.  El proceso de la cola ejecuta una vez el job que ha sido seleccionado por CJQ. El proceso ejecuta un job a la vez.

4.  Después que el proceso termina la ejecución de un job, sondea si existen más jobs, después se queda dormido, despertando en intervalos periódicos para sondear por nuevos jobs. Si el proceso no encuentra ningún job nuevo, luego se para después de un intervalo predefinido.

 El parámetro de inicialización JOB_QUEUE_PROCESSES representa el máximo número de colas de procesos jobs, que se pueden ejecutar de forma concurrente en una instancia

 Sin embargo el cliente no debe asumir que todos los procesos de cola de jons están disponibles para la ejecución de jobs.

 Nota:

El coordinador de procesos no se levanta si e parámetro de inicialización se pone a 0.

Para más información:

‘Oracle® Database Concepts 10g Release 2 (10.2)

‘Oracle® Database Administrator’s Guide10g Release 2 (10.2)’

How to control The Frequency That The Server Checks For New Scheduled Jobs

Tablas donde se guarda está información:

SQL> select JOB, LAST_DATE, NEXT_DATE, FAILURES from job$;
       JOB LAST_DATE          NEXT_DATE            FAILURES
---------- ------------------ ------------------ ----------
      4001 26-NOV-10          27-NOV-10                   0
      4002 26-NOV-10          26-NOV-10                   0
     23028                    26-NOV-10
     23027                    01-DEC-10

       JOB LAST_DATE          NEXT_DATE            FAILURES
---------- ------------------ ------------------ ----------
        22                    26-NOV-10                   4
        21                    26-NOV-10                   4
     23029                    26-NOV-10                   4
     23030                    26-NOV-10                   4
     23025                    26-NOV-10                   4

select NEXT_RUN_DATE from sys.scheduler$_job;
SQL>
NEXT_RUN_DATE
---------------------------------------------------------------------------
27-NOV-10 03.00.00.900000 AM GMT0
27-NOV-10 03.00.00.500000 AM GMT0

01-DEC-10 01.01.01.400000 AM +00:00
28-NOV-10 12.00.00.000000 AM +00:00

26-NOV-10 04.44.02.600000 PM +00:00
26-NOV-10 04.49.39.000000 PM +01:00
 

Activar y desactivar los jobs de un usuario:

Activarlos:

sqlplus ‘/ as sysdba’
SET SERVEROUTPUT ON;
DECLARE
CURSOR C_JOBS IS
select job,BROKEN from dba_jobs
where UPPER(schema_user)='<SCHEME_USER_IN_CAPITAL_LETTERS>';         
BEGIN
FOR VREG IN C_JOBS LOOP
BEGIN
IF VREG.BROKEN = 'Y' THEN
dbms_ijob.broken(VREG.JOB,FALSE);
END IF;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
END LOOP;
END;
/

Desactivarlos:

sqlplus ‘/ as sysdba’
SQL>     SET SERVEROUTPUT ON;
DECLARE
CURSOR C_JOBS IS
select job,BROKEN from dba_jobs
where UPPER(schema_user)='<SCHEME_USER_IN_CAPITAL_LETTERS>';       
BEGIN
FOR VREG IN C_JOBS LOOP
BEGIN
IF VREG.BROKEN = 'N' THEN
dbms_ijob.broken(VREG.JOB,TRUE);
END IF;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
END LOOP;
END;
/