Comment détecter avec précision si un travail SQL Server est en cours d'exécution et de traiter avec le travail déjà en cours d'exécution?

Je suis actuellement en utilisant ce type de code pour détecter si un travail SQL server est en cours d'exécution. (c'est SQL Server 2005, tous les SP)

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)
)

Pas de problèmes là-bas, et d'une manière générale, il fonctionne très bien.

Mais.... (toujours un mais)

À l'occasion, je vais appeler cette, retrouver un travail "n'est pas en cours d'exécution" résultat, à quel point je vais essayer de commencer le travail, via

exec msdb.dbo.sp_start_job @JobName

et SQL sera de retour que "SQLAgent a refusé de démarrer le travail car il a déjà une demande en attente".

Ok. Pas non plus un problème. Il est concevable qu'il existe une petite fenêtre où le travail de cible pourrait avoir commencé avant ce code peut démarrer, mais après vérification, si elle est lancée. Cependant, je peut simplement conclure que dans un try catch et simplement ignorer l'erreur, non?

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

voici le problème, cependant.

9 fois sur 10, cela fonctionne bien. L'agent SQL déclenche l'erreur, il est pris, et le traitement continue, tout simplement, parce que le travail est déjà en cours d'exécution, aucun mal, aucune faute.

Mais de temps en temps, je vais avoir un message dans l'Historique de Travail (vue de garder à l'esprit le code ci-dessus afin de détecter si un travail est en cours et commencer, s'il n'est effectivement en cours d'exécution à partir d'un autre poste de travail) en disant que la tâche a échoué parce que "SQLAgent a refusé de démarrer le travail car il a déjà une demande en attente".

Bien sûr, c'est l'erreur exacte que TRY CATCH est censé être de la manipulation!

Lorsque cela se produit, l'exécution de travail juste meurt, mais pas immédiatement de ce que je peux dire, juste assez proche. J'ai mis la journalisation de tous sur la place et il n'y a pas de cohérence. Une fois, il échoue, il sera à la place un, la prochaine fois au lieu de b. Dans certains cas, le Lieu A et lieu B n'ont rien, mais un

select @var = 'message'

entre eux. Très étrange. Fondamentalement, le travail semble être été jetés sans ménagement et rien à exécuter dans le travail est +pas+ tout exécuté.

Cependant, si je supprime le "exec StartJob" (ou de l'avoir invoqué exactement une fois, quand je SAIS que la tâche ne peut pas être en cours d'exécution), tout fonctionne parfaitement et tout mon traitement dans le travail s'exécute à travers.

Le but derrière tout cela, c'est d'avoir un travail qui a commencé comme un résultat d'un déclencheur (entre autres choses), et, si le travail est déjà commencé, il n'y a vraiment pas besoin de "recommencer".

Jamais quelqu'un courir dans des comportement comme ça avec l'Agent SQL du Travail de manipulation?

EDIT:
Flux de courant de contrôle comme suit:

  1. Changement d'un tableau (update ou insert)...
  2. active le déclencheur qui appelle...
  3. une procédure stockée qui appelle...
  4. sp_Start_Job...
  5. commence un travail spécifique qui...
  6. appelle une autre procédure stockée (appelé CheckQueue) qui...
  7. effectue un traitement et...
  8. vérifie plusieurs tables en fonction de leur contenu pourrait...
  9. invoquer sp_start_job sur un autre poste afin de démarrer une deuxième simultanée de l'emploi
    pour traiter le travail supplémentaire (ce deuxième emploi appelle la CheckQueue la procédure stockée également
    mais les deux invocations fonctionner sur des ensembles distincts de données)
Pas la réponse, je suis vraiment à la recherche d', mais comme une solution de contournement, j'ai créé un "moniteur" du tableau, qui contient un drapeau indiquant si chaque travail particulier est "vraiment" en cours d'exécution ou non, et le délai d'expiration pour se prémunir contre les défaillances. Donc, si ce drapeau indique un emploi n'est pas en cours d'exécution, il n'y a aucun moyen on peut être en cours d'exécution de sorte qu'il est sûr de le faire démarrer. Si il indique qu'il EST en cours d'exécution, j'utilise le sp_help_job méthode pour vérifier si le travail est en cours d'exécution. si cela renvoie que ce n'est PAS en cours d'exécution. Je bosse un compteur et continuer.
Si le compteur est tombé x fois dans une rangée avec une quantité de temps entre eux, alors je peux être raisonnablement certains que le travail n'est PAS en fait en cours d'exécution, clair de son état et de le rendre disponible pour l'exécuter à nouveau. Douleur dans le cul, mais il fonctionne toujours.
Espèrent encore un peu moins rond-point de la solution si

OriginalL'auteur DarinH | 2011-05-02