Procedimiento de Oracle para eliminar trabajos que no se completan en un tiempo determinado

Creé un procedimiento de Oracle para reprogramar el trabajo que no se completa en un período de tiempo determinado:

create or replace procedure kill_stuck_jobs
as
begin     
    for x in (  
            select j.sid,
                   s.spid,
                   s.serial#,
                   j.log_user,
                   j.job,
                   j.broken,
                   j.failures,
                   j.last_date,
                   j.this_date,
                   j.next_date,
                   j.next_date - j.last_date interval,
                   j.what
                  from 
                  (select 
                  djr.SID, 
                  dj.LOG_USER,
                  dj.JOB, 
                  dj.BROKEN,
                  dj.FAILURES, 
                  dj.LAST_DATE,
                  dj.LAST_SEC,
                  dj.THIS_DATE, dj.THIS_SEC, 
                  dj.NEXT_DATE, dj.NEXT_SEC, dj.INTERVAL, dj.WHAT
                  from dba_jobs dj, dba_jobs_running djr
                  where dj.job = djr.job ) j,
                  (select p.spid, s.sid, s.serial#
                  from v$process p, v$session s
                  where p.addr = s.paddr ) s
                  where j.sid = s.sid and 
                  j.next_date+15/1440 < sysdate  
        ) loop  
         EXEC DBMS_JOB.BROKEN(x.job,TRUE);
         execute immediate 'alter system disconnect session '''|| x.sid|| ',' || x.serial# || ''' immediate';
         EXEC DBMS_JOB.BROKEN(x.job,FALSE);
         dbms_output.put_line( 'Alter session done' );             
    end loop;  
end;  

Pero este procedimiento compila con error:

PLS-00103: Encountered the symbol "DBMS_JOB" when expecting one of the following:

   := . ( @ % ;
The symbol ":=" was substituted for "DBMS_JOB" to continue.

enter image description here

  • Aquí vino la discusión sobre dbms_job y dbms_scheduler_job. En realidad, el problema aquí es que creé una vista materializada usando una base de datos vinculada, pero en algún momento la consulta se atasca durante todo el día en la sesión con SQL*Net more data from dblink . Usé el procedimiento anterior para eliminar los trabajos que se crean al crear una vista materializada y estoy eliminando la sesión usando:

    create or replace procedure kill_stuck_refresh as 
     begin     
         for x in (  
                select username, osuser, sid, serial#, seconds_in_wait, 
                event, state, wait_class
                from v$session
                where username is not null 
                      and seconds_in_wait > 600 
                      and event = 'SQL*Net more data from dblink'  
            ) loop  
            execute immediate 'alter system disconnect session '''|| x.sid  
                         || ',' || x.serial# || ''' immediate';
            dbms_output.put_line( 'Alter session done' );             
         end loop;  
       end; -- end of kill_stuck_refresh; 
    

preguntado el 22 de mayo de 12 a las 07:05

4 Respuestas

Su pila de errores se deriva del hecho de que su cursor no es válido. La causa es el ORA-00942. Esto puede significar que el nombre de la tabla está mal escrito, pero como está usando el diccionario de datos, generalmente indica un problema de permisos, es decir, las tablas (o las vistas en este caso) no existen en su ámbito.

Lo que nos lleva a tu comentario:

"Puedo ejecutar la consulta de selección de forma independiente, creo que eso significa que tengo esos privilegios".

Esto me sugiere que sus permisos se han otorgado a un rol sobre el que tiene derechos. Podemos usar los permisos otorgados a través de roles en SQL, pero no podemos usarlos para crear objetos permanentes, como vistas o procedimientos almacenados. Para que esto funcione, debe tener permisos en esas vistas otorgados directamente a su usuario. No hay solución alternativa, así es como funciona el modelo de seguridad de Oracle.


Por cierto, debería investigar por qué estos trabajos tardan demasiado. Supongo que este es un problema persistente (de lo contrario, ¿por qué está creando un proceso almacenado para eliminar estos trabajos?). Eliminar puestos de trabajo es un instrumento contundente que desperdicia recursos y borra pruebas útiles. Una mejor idea sería averiguar la causa subyacente del bajo rendimiento y solucionarlo. Tal vez haya un problema con el bloqueo de sesiones y necesite una estrategia de bloqueo. Tal vez tengas un SQL mal ajustado. Algún otro trabajo puede estar ejecutándose al mismo tiempo y absorber todos los recursos, en cuyo caso necesita un programador decente. O es posible que ahora tenga más datos (el precio del éxito) y necesite dar más tiempo a los trabajos para completarlos.

contestado el 22 de mayo de 12 a las 11:05

¿podría explicar la sesión de bloqueo y la estrategia de bloqueo? El SQL está ajustado ya que tarda solo 7 segundos la mayor parte del tiempo, pero como está vinculado a la base de datos en algún momento durante la mañana y la noche mientras el sistema remoto está ocupado, simplemente permanece en sesión. - kinkajú

e incluso el usuario del SISTEMA (el usuario que se crea al instalar Oracle Express) no puede compilar este procedimiento. - kinkajú

Usted no necesita EXEC en este contexto (en un procedimiento/función almacenados). Solo es necesario cuando desea llamar a un procedimiento almacenado desde SQL (desde SQL*Plus). Solo llama dbms_job.broken() directamente:

...
DBMS_JOB.BROKEN(x.job,TRUE);
execute immediate 'alter system disconnect session '''|| x.sid|| ',' || x.serial# || ''' immediate';
DBMS_JOB.BROKEN(x.job,FALSE);
dbms_output.put_line( 'Alter session done' );
...

contestado el 22 de mayo de 12 a las 07:05

Todavía no se ha compilado correctamente. He adjuntado un archivo de error en el desarrollador de sql. no se cual es el problema - kinkajú

¿Tienes acceso a dba_* y v$* ¿mesas? Por lo general, solo las cuentas de administrador (SYS, SYSTEM) tienen acceso a estos. Si no tiene acceso, deberá tener los privilegios necesarios (por ejemplo, GRANT SELECT ON sys.v$_process TO <username>;). No sería prudente crear y ejecutar ningún código en estas cuentas; es mejor tener los privilegios necesarios (y solo esos) otorgados a un usuario con derechos limitados. - Szilard Barany

Es posible que desee utilizar ALTER SYSTEM KILL SESSION <sid>, <serial#>;. Desconectar una sesión parece bastante brutal; matarlo 'revertiría las transacciones en curso, liberaría todos los bloqueos de sesión y recuperaría parcialmente los recursos de la sesión". - Szilard Barany

Puedo ejecutar la consulta de selección de forma independiente, creo que eso significa que tengo esos privilegios. Sin embargo, cambié la desconexión para matar ... pero aún compilé con error ... - kinkajú

Tengo el mismo error, se trata de v$session. En realidad no se trata v$session porque si cambio el orden de las tablas entonces se queja de v$process. Tengo un vago recuerdo sobre un problema muy similar, pero no puedo recordar los detalles. No tenía nada que ver con los privilegios. Le haré saber si puedo recordar cuál fue el problema (y la solución). - Szilard Barany

Como mencionó @David Aldridge, DBMS_Scheduler está destinado en gran medida a reemplazar DBMS_Job (comenzando con 10g, en realidad). Lo que no mencionó es por qué esto te ayudaría.

DBMS_Scheduler proporciona mucho más control sobre sus trabajos, incluido un mejor registro. Sin embargo, lo más significativo para usted es que DBMS_Scheduler agrega un max_run_duration parámetro al trabajo. Si el tiempo de ejecución de un trabajo supera esa duración, el trabajo finaliza automáticamente (y probablemente de una manera más elegante que si se eliminara la sesión). Entonces, mientras el max_failures el parámetro no está configurado, el trabajo se intentará nuevamente en su próxima hora programada.

Si puede migrar sus trabajos actuales a DBMS_Scheduler, puede ahorrarse la molestia de escribir código para proporcionar la funcionalidad que ya existe.

contestado el 22 de mayo de 12 a las 15:05

buena explicación para principiantes como yo, pero es una vista materializada que está creando el trabajo. - kinkajú

Si usa Oracle 11g, entonces debería usar DBMS_Scheduler, no DBMS_Job. Mire primero la migración al nuevo paquete y reconsidere su requisito en ese contexto.

contestado el 22 de mayo de 12 a las 10:05

Este es un consejo sensato, pero en realidad no responde la pregunta. - APC

De hecho, pero sí sugiere un curso de acción a seguir por el interrogador. - david aldrid

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.