Puis-je lancer une procédure stockée et revenir immédiatement sans attendre la fin?

41

Nous avons une procédure stockée que les utilisateurs peuvent exécuter manuellement pour obtenir des numéros mis à jour pour un rapport utilisé constamment tout au long de la journée.

J'ai une deuxième procédure stockée qui doit être exécutée après la première procédure stockée, car elle est basée sur les nombres obtenus à partir de cette première procédure stockée. Toutefois, son exécution est plus longue et concerne un processus séparé. Je ne souhaite donc pas faire patienter l'utilisateur pendant l'exécution de cette deuxième procédure stockée.

Existe-t-il un moyen de faire en sorte qu'une procédure stockée démarre une seconde procédure stockée et revienne immédiatement sans attendre les résultats?

J'utilise SQL Server 2005.

Rachel
la source
Comment les procédures stockées sont-elles appelées? Application Web ASP.NET? SSRS?
Mr.Brownstone
@ Mr.Brownstone Il est généralement appelé à partir d'une application Web ASP.Net, même si plusieurs d'entre eux l'appellent. Je devrais vérifier. Il est également parfois exécuté manuellement à partir de SSRS.
Rachel
@MartinSmith J'ai déjà travaillé avec SQL Service Broker dans le passé et j'espérais qu'il y aurait un moyen plus simple. Cela ressemble à une configuration complexe pour quelque chose d'aussi simple que cela.
Rachel
1
@MartinSmith c'est à peu près ce que je pensais - de même, pour SSRS non, vous ne pouvez pas mais vous pouvez faire, c'est incorporer Report Viewer dans l'application et y déplacer votre RDL - de cette façon, il serait possible de passer des appels asynchrones. pour les rapports aussi.
Mr.Brownstone

Réponses:

27

Il semble y avoir de nombreuses façons d’y parvenir, mais j’ai trouvé que le moyen le plus simple était de suggérer à Martin d’établir la procédure dans un travail SQL et de le démarrer à l’aide de la commande asynchrone sp_start_job de ma procédure stockée.

EXEC msdb.dbo.sp_start_job @job_name='Run2ndStoredProcedure'

Cela ne fonctionne que pour moi car je n'ai pas besoin de spécifier de paramètres pour ma procédure stockée.

D’autres suggestions qui peuvent fonctionner en fonction de votre situation sont

  • Utilisation de SQL Service Broker, comme le suggèrent Martin et Sebastian . C'est probablement la meilleure suggestion si la complexité de son installation et de son fonctionnement ne vous dérange pas.
  • Exécuter le processus de manière asynchrone dans le code responsable de l’exécution de la procédure stockée, comme l’ a suggéré M.Brownstone .

    Ce n'est pas une mauvaise idée, mais dans mon cas, la procédure stockée est appelée depuis plusieurs endroits. Trouver tous ces endroits et veiller à ce qu'ils appellent la deuxième procédure ne semblait pas très pratique. En outre, la deuxième procédure stockée est assez critique, et l’oubli de son exécution pourrait entraîner des problèmes majeurs pour notre société.

  • Définissez un indicateur pour la première procédure et configurez un travail récurrent pour vérifier cet indicateur et l'exécuter, comme l'a suggéré Jimbo . Je ne suis pas un grand partisan des travaux en cours qui vérifient les modifications toutes les quelques minutes, mais c'est certainement une option à considérer en fonction de votre situation.
Rachel
la source
4
Consultez Exécution de la procédure asynchrone pour obtenir un exemple prêt à l'emploi avec Service Broker. L'avantage par rapport à sp_job est qu'il fonctionne sous Express Edition et qu'il est entièrement contenu dans une base de données (aucune dépendance sur les tables de travail MSDB). Cette dernière est très importante pour le basculement DBM et la récupération HA / DR.
Remus Rusanu
Shoot, je vois que Martin a lié le même article. Je vais laisser le commentaire pour les arguments failover / DR.
Remus Rusanu
@RemusRusanu: eh bien, c'est l'une des meilleures sources d'informations concernant Service Broker, mais je suppose que vous le saviez déjà ;-).
Marian
J'ai aimé le lien de @Rusanu, mais je voulais quelque chose sans réponse (qui, je pense, correspond à ce problème). J'ai rédigé ma version simplifiée sur abamacus.blogspot.com/2016/05/…
Abaque
De même, si vous essayez de démarrer un travail d'agent SQL, il échouera si The EXECUTE permission was denied on the object 'sp_start_job', database 'msdb', schema 'dbo'.Service ni Broker, ni SQL Agent n'existent également sur Azure. J'ignore pourquoi, après une quinzaine d'années, Microsoft refuse d'ajouter EXECUTE ASYNC RematerializeExpensiveCacheTable.
Ian Boyd
8

Vous pouvez utiliser Service Broker avec l'activation de la file d'attente. Avec cela, vous pouvez enregistrer les paramètres de l'appel de procédure dans la file d'attente. Cela prend à peu près autant de temps qu’un insert. Une fois la transaction validée et éventuellement quelques secondes de plus, l'activation appelle automatiquement la procédure de destinataire de manière asynchrone. Il ne reste plus qu’à prendre les paramètres de la file d’attente et à effectuer le travail souhaité.

Sebastian Meine
la source
7

Cette vieille question mérite une réponse plus complète. Certains d'entre eux sont mentionnés dans d'autres réponses / commentaires ici, d'autres peuvent ou ne peuvent pas fonctionner pour la situation spécifique de OP, mais peuvent fonctionner pour d'autres recherchant des appels stockés de manière asynchrone à partir de SQL.

Pour être tout à fait explicite, TSQL n’a pas (à lui seul) la capacité de lancer d’autres opérations TSQL de manière asynchrone .

Cela ne signifie pas que vous n'avez pas encore beaucoup d'options:

  • Travaux de l'agent SQL : créez plusieurs travaux SQL et planifiez-les de s'exécuter à l'heure souhaitée ou démarrez-les de manière asynchrone à partir d'un "contrôle maître" enregistré en utilisant sp_start_job. Si vous devez surveiller leur progression par programme, assurez-vous simplement que les travaux mettent à jour une table JOB_PROGRESS personnalisée (ou vous pouvez vérifier s'ils ont déjà fini d'utiliser la fonction non documentée xp_sqlagent_enum_jobsdécrite dans cet excellent article. de Gregory A. Larsen). Vous devez créer autant de travaux distincts que vous souhaitez que des processus parallèles soient exécutés, même s'ils exécutent le même processus stocké avec des paramètres différents.
  • Package SSIS : pour des scénarios asynchrones plus complexes, créez un package SSIS avec un simple flux de tâches de branchement. SSIS lancera ces tâches dans des spids individuels, que SQL exécutera en parallèle. Appelez le package SSIS à partir d'un travail d'agent SQL.
  • Application personnalisée : écrivez une application personnalisée simple dans la langue de votre choix (C #, Powershell, etc.), à l'aide des méthodes asynchrones fournies par cette langue. Appeler un proc stocké SQL sur chaque thread d'application.
  • Automatisation OLE : En SQL, utilisez sp_oacreateet sp_oamethodpour lancer un nouveau processus s'appelant un processus enregistré, comme décrit dans cet article , également par Gregory A. Larsen.
  • Service Broker : examinez l'utilisation de Service Broker , un bon exemple d'exécution asynchrone dans cet article .
  • Exécution parallèle du CLR : utilisez les commandes CLR Parallel_AddSqlet Parallel_Executecomme décrit dans cet article par Alan Kaplan (SQL2005 + uniquement).
  • Tâches Windows planifiées : répertoriées pour être complètes, mais je ne suis pas fan de cette option.

Si c'était moi, j'utiliserais probablement plusieurs jobs d'agent SQL dans des scénarios plus simples et un package SSIS dans des scénarios plus complexes.

Dans votre cas, appeler des tâches SQL Agent semble être un choix simple et gérable.

Un dernier commentaire : SQL tente déjà de paralléliser des opérations individuelles chaque fois qu'il le peut *. Cela signifie que l'exécution de 2 tâches en même temps plutôt que les unes après les autres ne garantit en aucun cas qu'elle se terminera plus tôt. Testez soigneusement pour voir si cela améliore réellement quelque chose ou non.

Un développeur a créé un package DTS pour exécuter 8 tâches simultanément. Malheureusement, ce n'était qu'un serveur à 4 processeurs :)

* En supposant les paramètres par défaut. Cela peut être modifié en modifiant le degré maximum de parallélisme ou le masque d'affinité du serveur ou en utilisant l'indicateur de requête MAXDOP.

BradC
la source
Salut Brad. Je dois croire que vous pouvez démarrer plusieurs tâches d'agent SQL à partir d'une seule tâche d'agent SQL et qu'elles s'exécutent de manière asynchrone. Je crois que le seul critère de succès au niveau de l'emploi parent est qu'un sous-emploi a été créé. L'échec (je pense) ne peut être constaté qu'en consultant l'historique des sous-travaux.
user8591443
@ user8591443 Ce travail principal que vous décrivez devrait utiliser un script SQL qui lançait les autres travaux via sp_start_job, comme je le décris dans mon premier point (étant donné qu'il n'y a pas de type d'étape de travail intégré consistant à "démarrer un autre travail"). Mais je pense que vous avez raison de dire que les statuts de travail individuels ne sont pas transmis au maître; vous devez interroger le statut échec / succès individuellement.
BradC
oui, chaque étape de l'agent (une pour chaque travail) du travail de l'agent SQL principal aurait un exécutant t-sql distinct sp_start_job.
user8591443
6

Oui, une méthode:

  1. Lorsque la 1ère procédure stockée est terminée, elle insère un enregistrement avec toutes les informations nécessaires à l'exécution de la seconde procédure stockée.
  2. La deuxième procédure stockée est exécutée à la minute près ou à l’heure choisie.
  3. Il vérifie les enregistrements insérés, effectue son traitement et marque l'enregistrement comme complet.
Jimbo
la source
Cela limite l’exécution de la procédure stockée au nombre de tâches en cours d’exécution qui ne vous conviennent que si vous ne souhaitez que cela soit appelé par un client à la fois - alors que plusieurs clients peuvent appeler la même procédure en même temps . De plus, comment le client peut-il savoir que le travail est terminé sans interroger à plusieurs reprises la base de données pour déterminer si un indicateur a été défini?
Mr.Brownstone
1
@ Mr.Brownstone - Le travail pourrait éventuellement traiter plusieurs tâches en attente mises en file d'attente par différents appels de procédures stockées lors de son exécution. La procédure stockée peut également éventuellement appeler sp_start_jobpour la démarrer ou créer des tâches selon les besoins de manière dynamique pour éviter toute interrogation, mais la complexité de ce cas signifie probablement que ce ne sera pas plus simple que service broker.
Martin Smith
@MartinSmith En fait, ma tâche est déjà configurée pour cette deuxième procédure stockée, car elle était exécutée tous les soirs jusqu'à ce que nous ayons constaté des problèmes de synchronisation avec les numéros de la première procédure. Si je lance le travail à partir de la première procédure stockée, est-ce qu'il s'exécute de manière asynchrone et est renvoyé du SP immédiatement?
Rachel
@ Rachel - Oui. sp_start_jobrevient immédiatement. Je ne me souviens plus des autorisations dont il a besoin.
Martin Smith
1
Le démarrage d'un travail à partir d'une autre procédure / base de données est un problème assez complexe si vous ne voulez pas ouvrir de grandes failles de sécurité. Erland Sommarskog a publié un article sur les différentes techniques à combiner: sommarskog.se/grantperm.html Il n’existe cependant aucune solution complète.
Sebastian Meine
1

Une autre possibilité serait d’écrire la 1ère procédure stockée dans une table d’audit une fois celle-ci terminée et de placer un déclencheur sur la table d’audit qui lance la 2e procédure stockée lors de l’écriture de la table d’audit. Pas besoin d'interroger en permanence et pas besoin d'un travail supplémentaire de l'Agent SQL Server.

paco
la source
3
La première procédure stockée ne serait pas renvoyée avant la fin de l'insertion dans la table d'audit, ce qui ne se produirait pas tant que le déclencheur n'aurait pas terminé son exécution (y compris l'appel de la 2e procédure stockée)
Martin Smith
1
J'ai déjà envisagé d'utiliser un déclencheur, mais les déclencheurs sont exécutés de manière synchrone avec l' instruction INSERTor UPDATE, et non de manière asynchrone. Martin a donc raison de dire que la 1ère procédure finira par attendre que la 2e procédure se termine.
Rachel le