Actualmente estoy usando un código como este para detectar si se está ejecutando un trabajo de SQL Server. (Esto es SQL Server 2005, todos de SP)¿Cómo detectar con precisión si un trabajo de SQL Server se está ejecutando y lidiar con el trabajo que ya se está ejecutando?
return (select isnull(
(select top 1 CASE
WHEN current_execution_status = 4 THEN 0
ELSE 1
END
from openquery(devtestvm, 'EXEC msdb.dbo.sp_help_job')
where current_execution_status = 4 and
name = 'WQCheckQueueJob' + cast(@Index as varchar(10))
), 1)
)
No hay problema, y en términos generales, funciona muy bien.
Pero .... (siempre hay un pero)
De vez en cuando, voy a llamar a esta, vuelva un "trabajo no se está ejecutando" número, momento en el que voy a tratar de iniciar el trabajo, a través de
exec msdb.dbo.sp_start_job @JobName
y SQL retornará que "SQLAgent se ha negado a iniciar el trabajo porque ya tiene una solicitud pendiente".
Ok. Tampoco es un problema. Es concebible que haya una pequeña ventana donde el trabajo objetivo podría comenzar antes de que este código pueda iniciarlo, pero luego de verificar si se inició. Sin embargo, puedo terminar eso en un try catch y simplemente ignorar el error, ¿verdad?
begin try
if dbo.WQIsQueueJobActive(@index) = 0 begin
exec msdb.dbo.sp_start_job @JobName
break
end
end try begin catch
-- nothing here
end catch
aquí está el problema, sin embargo.
9 veces de cada 10, esto funciona bien. El agente SQL generará un error, se detectará y el procesamiento continuará, ya que el trabajo ya se está ejecutando, no hay daño ni falta.
Pero de vez en cuando, aparece un mensaje en la vista Historial de trabajos (recuerde el código anterior para detectar si un trabajo específico se está ejecutando y ejecútelo si no se está ejecutando desde otro trabajo) diciendo que el trabajo falló porque "SQLAgent se ha negado a comenzar el trabajo porque ya tiene una solicitud pendiente".
¡Por supuesto, este es el error exacto que se supone que TRY CATCH debe manejar!
Cuando esto sucede, el trabajo de ejecución simplemente muere, pero no inmediatamente de lo que puedo decir, solo muy cerca. He puesto el registro por todos lados y no hay consistencia. Una vez que falla, estará en el lugar a, la próxima vez en el lugar b. En algunos casos, el Lugar A y el lugar B no tienen nada más que un
select @var = 'message'
entre ellos. Muy extraño. Básicamente, el trabajo parece ser abandonado sin ceremonias y todo lo que queda por ejecutar en el trabajo es + no + ejecutado en absoluto.
Sin embargo, si elimino el "exec StartJob" (o lo invoco exactamente una vez, cuando SÉ que el trabajo objetivo no se puede ejecutar), todo funciona perfectamente y todo mi procesamiento en el trabajo se ejecuta .
El objetivo de todo esto es iniciar un trabajo como resultado de un desencadenador (entre otras cosas) y, si el trabajo ya se ha iniciado, realmente no hay necesidad de "iniciarlo de nuevo".
¿Alguien alguna vez ha tenido un comportamiento como este con el manejo de trabajos del Agente SQL?
EDIT: El flujo de corriente de control es de esta manera:
- Cambio a una tabla (actualización o inserción) ...
- incendios de disparo que llama ...
- un procedimiento almacenado que llama a ...
- sp_start_job cual ...
- comienza un trabajo específico que ...
- llama a otro procedimiento almacenado (llamado CheckQueue), que ...
- realiza alguna procesamiento y ...
- cheques varias mesas y en función de sus contenidos podría ...
- invocación sp_start_job en otro puesto de trabajo para poner en marcha un segundo, el trabajo simultáneo para procesar el trabajo adicional (este segundo trabajo llama al procedimiento almacenado CheckQueue también pero las dos invocaciones operan en conjuntos de datos completamente separados)
No es la respuesta que realmente estoy buscando, pero como una solución, he creado una tabla de "monitor", que contiene una bandera que indica si cada trabajo en particular es "realmente" en ejecución o no, y el tiempo de expiración hasta proteger contra los fracasos. Por lo tanto, si este indicador indica que un trabajo no se está ejecutando, no hay manera de que se pueda ejecutar, por lo que es seguro iniciarlo. Si indica que se está ejecutando, uso el método sp_help_job para verificar si el trabajo se está ejecutando. si eso devuelve que NO se está ejecutando. Choco con un mostrador y continúo. – DarinH
Si el contador se golpea x veces seguidas con una cantidad de tiempo entre ellas, entonces puedo estar razonablemente seguro de que el trabajo NO se está ejecutando realmente, borrar su estado y ponerlo a disposición para volver a ejecutarlo. Dolor en el trasero, pero funciona de manera consistente. – DarinH
Aún espero una solución un poco menos indirecta, aunque – DarinH