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:
- Changement d'un tableau (update ou insert)...
- active le déclencheur qui appelle...
- une procédure stockée qui appelle...
- sp_Start_Job...
- commence un travail spécifique qui...
- appelle une autre procédure stockée (appelé CheckQueue) qui...
- effectue un traitement et...
- vérifie plusieurs tables en fonction de leur contenu pourrait...
- 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)
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
Vous devez vous connecter pour publier un commentaire.
Tout d'abord, avez-vous eu la chance d'aller au service broker? À partir de votre description, il semble que c'est ce que vous voulez vraiment.
La différence serait plutôt de commencer un travail, vous mettez vos données en un SB de la file d'attente et SB appelle votre traitement proc de manière asynchrone et complètement à côté de l'étape problèmes avec la déjà en cours d'exécution d'emplois, etc.. Il sera automatiquement spawn/mettre fin à plus de threads et de la demande l'exige, il prend soin de la commande etc.
Ici est une bonne (et vaguement liés) tutoriel. http://www.sqlteam.com/article/centralized-asynchronous-auditing-with-service-broker
Supposons que vous ne pouvez pas utiliser SB pour quelque raison que ce soit (mais sérieusement, y faire!).
Que sur l'utilisation de l'emploi du spid context_info.
La première instruction à l'intérieur de l'emballage du proc est
Lors de votre proc finitions (ou dans un bloc catch)
Lorsque vous êtes à la recherche à l'appel de votre travail, faites ceci:
Lors de votre enveloppe proc se termine, ou que la connexion est fermée, votre context_info s'en va.
Vous pouvez également utiliser un mondial de la table temporaire (c'est à dire ##JobStatus) Ils disparaissent lorsque tous les spid qu'il référence à déconnecter ou si c'est explicitement supprimé.
Juste quelques pensées.
J'ai regardé dans ServiceBroker au départ, mais que le client a mis son veto que comme ils n'avaient pas un qui ne connaissait rien à ce sujet sur le personnel. Encore, la servicebroker truc est définitivement sur ma tête pour de futurs projets. Merci!
Je suis en train de donner cette réponse le nod, principalement parce que 1) il mentionne CONTEXT_INFO qui je n'avais pas utilisé avant, et 2) c'est essentiellement ce que je me suis retrouvé avec l'aide d'un Travail de Suivi de la table, même si au niveau Mondial de la table temporaire peut être un +peu+ plus propre, en ce qu'elle tend à nettoyer après lui-même automatiquement, alors qu'avec un tableau normal, je devais m'assurer que les choses se sont nettoyés de manière explicite.
OriginalL'auteur Code Magician
J'ai une requête qui me donne l'travaux en cours d'exécution, peut-être que cela peut vous aider. Il a travaillé pour moi, mais si vous trouvez une faute sur elle, laissez-moi savoir, je vais essayer de rectifier. des acclamations.
OriginalL'auteur marcello miorelli
De Traiter avec un emploi déjà en cours d'exécution:
1. Ouvrez Le Gestionnaire Des Tâches
2. Vérifier si un Processus avec Nomimage "DTExec.exe" est en cours d'exécution
3. Si le processus est en cours et si c'est le travail qui pose problème, exécutez "terminer le Processus".
OriginalL'auteur Menahem