Posso avviare una procedura memorizzata e tornare immediatamente senza attendere che finisca?


41

Abbiamo una procedura memorizzata che gli utenti possono eseguire manualmente per ottenere alcuni numeri aggiornati per un report che viene utilizzato costantemente durante il giorno.

Ho una seconda procedura memorizzata che dovrebbe essere eseguita dopo l'esecuzione della prima procedura memorizzata poiché si basa sui numeri ottenuti da questa prima procedura memorizzata, tuttavia richiede più tempo per l'esecuzione ed è per un processo separato, quindi non voglio far attendere l'utente mentre viene eseguita questa seconda procedura memorizzata.

C'è un modo per avere una procedura memorizzata avviare una seconda procedura memorizzata e tornare immediatamente senza attendere i risultati?

Sto usando SQL Server 2005.


Come vengono chiamate le stored procedure? Applicazione Web ASP.NET? SSRS?
Mr.Brownstone,


@ Mr.Brownstone Di solito viene chiamato da un'applicazione Web ASP.Net, sebbene possa essere chiamato da più di una di esse. Dovrei ricontrollare. Occasionalmente viene anche eseguito manualmente da SSRS.
Rachel,

@MartinSmith In passato ho lavorato con il broker del servizio SQL e speravo che ci sarebbe stato un modo più semplice. Sembra una configurazione così complessa per qualcosa di così semplice.
Rachel,

1
@MartinSmith è praticamente quello che stavo pensando - inoltre, come per SSRS no non puoi ma quello che potresti fare è incorporare Report Viewer nell'applicazione e spostare i tuoi rdl in esso - in questo modo sarebbe possibile effettuare chiamate asincrone anche per i rapporti.
Mr.Brownstone,

Risposte:


27

Sembra che ci siano molti modi per farlo, ma ho scoperto che il modo più semplice era il suggerimento di Martin di impostare la procedura in un processo SQL e avviarlo usando il comando asincrono sp_start_job dalla mia procedura memorizzata.

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

Questo funziona solo per me perché non ho bisogno di specificare alcun parametro per la mia procedura memorizzata.

Altri suggerimenti che potrebbero funzionare a seconda della situazione sono

  • Utilizzando il Service Broker SQL come Martin e Sebastian suggeriscono. Questo è probabilmente il miglior suggerimento se non ti dispiace la complessità di configurarlo e imparare come funziona.
  • Esecuzione asincrona del processo nel codice responsabile dell'esecuzione della procedura memorizzata, come suggerito da Mr.Brownstone .

    Non è una cattiva idea, tuttavia nel mio caso la procedura memorizzata viene chiamata da più punti, quindi trovare tutti quei posti e assicurarsi che chiamino anche la seconda procedura non sembra così pratico. Inoltre, la seconda procedura memorizzata è piuttosto critica e dimenticare di eseguirla potrebbe causare alcuni gravi problemi alla nostra azienda.

  • Imposta la prima procedura per impostare un flag e imposta un processo ricorrente per verificare tale flag ed esegui se impostato, come suggerito Jimbo . Non sono un grande fan dei lavori che vengono eseguiti costantemente e controllano le modifiche ogni pochi minuti, ma sicuramente è un'opzione che vale la pena considerare a seconda della situazione.

3
Dai un'occhiata all'esecuzione della procedura asincrona per un esempio pronto all'uso con Service Broker. Il vantaggio rispetto a sp_job è che funziona su Express Edition ed è interamente contenuto in DB (nessuna dipendenza dalle tabelle di lavoro MSDB). Il successivo è molto importante nel failover DBM e sul recupero HA / DR.
Remus Rusanu,

Spara, vedo che Martin ha collegato lo stesso articolo. Lascerò il commento per gli argomenti di failover / DR.
Remus Rusanu,

@RemusRusanu: beh, questa è una delle migliori fonti di informazioni su Service Broker, ma suppongo tu lo sapessi già ;-).
Marian,

Mi è piaciuto il link di @Rusanu, ma volevo qualcosa senza risposta (che penso corrisponda a questo problema). Ho scritto la mia versione semplificata su abamacus.blogspot.com/2016/05/…
Abacus

Inoltre, se si tenta di avviare un processo di Agente SQL, non funzionerà con EXECUTE permission was denied on the object 'sp_start_job', database 'msdb', schema 'dbo'.Anche il Service Broker, né Agente SQL, esiste in Azure. Non so perché Microsoft, dopo un decennio e mezzo di persone, si rifiuta di aggiungere EXECUTE ASYNC RematerializeExpensiveCacheTable.
Ian Boyd,

8

È possibile utilizzare il broker di servizi insieme all'attivazione sulla coda. Con ciò è possibile pubblicare i parametri per la chiamata di procedura sulla coda. Ciò richiede circa il tempo di un inserto. Dopo il commit della transazione e potenzialmente qualche secondo in più, l'attivazione chiamerà automaticamente la procedura del destinatario in modo asincrono. Dovrebbe semplicemente prendere i parametri della coda e fare il lavoro desiderato.


7

Questa vecchia domanda merita una risposta più completa. Alcuni di questi sono menzionati in altre risposte / commenti qui, altri potrebbero funzionare o meno per la situazione specifica di OP, ma potrebbero funzionare per altri che cercano chiamate memorizzate in modo asincrono da SQL.

Giusto per essere totalmente esplicito: TSQL non ha (da solo) la possibilità di avviare altre operazioni TSQL in modo asincrono .

Ciò non significa che non hai ancora molte opzioni:

  • Processi SQL Agent : creare più processi SQL e pianificarli per l'esecuzione all'ora desiderata oppure avviarli in modo asincrono da un proc memorizzato "controllo principale" mediante sp_start_job. Se devi monitorare i loro progressi in modo programmatico, assicurati solo che i lavori aggiornino ciascuno una tabella JOB_PROGRESS personalizzata (oppure puoi verificare se hanno terminato di utilizzare la funzione non documentata xp_sqlagent_enum_jobscome descritto in questo eccellente articolo di Gregory A. Larsen). È necessario creare tutti i processi separati desiderati per l'esecuzione di processi paralleli, anche se stanno eseguendo lo stesso proc memorizzato con parametri diversi.
  • Pacchetto SSIS : per scenari asincroni più complicati, creare un pacchetto SSIS con un semplice flusso di attività di ramificazione. SSIS avvierà tali attività in singoli spid, che SQL eseguirà in parallelo. Chiamare il pacchetto SSIS da un processo dell'agente SQL.
  • Applicazione personalizzata : scrivi una semplice app personalizzata nella lingua che preferisci (C #, Powershell, ecc.), Usando i metodi asincroni forniti da quella lingua. Chiama un proc memorizzato SQL su ogni thread dell'applicazione.
  • Automazione OLE : in SQL, utilizzare sp_oacreatee sp_oamethodavviare un nuovo processo chiamando l'altro proc memorizzato come descritto in questo articolo , anche da Gregory A. Larsen.
  • Service Broker : esaminare l'utilizzo di Service Broker , un buon esempio di esecuzione asincrona in questo articolo .
  • Esecuzione parallela CLR : utilizzare i comandi CLR Parallel_AddSqle Parallel_Executecome descritto in questo articolo di Alan Kaplan (solo SQL2005 +).
  • Attività di Windows pianificate : elencate per completezza, ma non sono un fan di questa opzione.

Se fossi in me, probabilmente utilizzerei più lavori SQL Agent in scenari più semplici e un pacchetto SSIS in scenari più complessi.

Nel tuo caso, chiamare i lavori di SQL Agent sembra una scelta semplice e gestibile.

Un commento finale : SQL tenta già di parallelizzare le singole operazioni ogni volta che può *. Ciò significa che eseguire 2 attività contemporaneamente invece che una dopo l'altra non garantisce che finirà prima. Prova attentamente per vedere se migliora effettivamente qualcosa o no.

Avevamo uno sviluppatore che ha creato un pacchetto DTS per eseguire 8 attività contemporaneamente. Sfortunatamente, era solo un server a 4 CPU :)

* Supponendo le impostazioni predefinite. Questo può essere modificato modificando il grado massimo di parallelismo o maschera di affinità del server o utilizzando il suggerimento per la query MAXDOP.


6

Sì, un metodo:

  1. Quando la prima procedura memorizzata è completa, inserisce un record con tutte le informazioni necessarie per l'esecuzione della seconda procedura memorizzata
  2. La seconda procedura memorizzata viene eseguita come lavoro, ogni minuto o a che ora decidi
  3. Verifica la presenza di record inseriti, esegue il processo e contrassegna il record come completo

Ciò limita l'esecuzione della procedura memorizzata al numero di lavori in esecuzione che, se si desidera che venga chiamato solo da un client alla volta, va bene, mentre è possibile che più client chiamino la stessa procedura contemporaneamente . Inoltre, come può il client sapere che il lavoro è stato completato senza eseguire ripetutamente il polling del database per scoprire se è stato impostato un flag?
Mr.Brownstone,

1
@ Mr.Brownstone - Potenzialmente il lavoro potrebbe elaborare più di un'attività in sospeso accodata da diverse chiamate di procedure memorizzate durante l'esecuzione. La procedura memorizzata potrebbe anche chiamare sp_start_jobper avviarla o creare lavori secondo necessità in modo dinamico per evitare il polling ogni minuto, ma la complessità per quel caso probabilmente significa che non sarà più semplice del broker di servizi.
Martin Smith,

@MartinSmith In realtà ho già una configurazione del lavoro per questa seconda procedura memorizzata poiché era in esecuzione di notte fino a quando non abbiamo riscontrato alcuni problemi con la sincronizzazione non corretta con i numeri della prima procedura. Se avessi avviato il lavoro dalla prima procedura memorizzata, sarebbe stato eseguito in modo asincrono e sarebbe tornato immediatamente dall'SP?
Rachel,

@ Rachel - Sì. sp_start_jobritorna immediatamente. Non ricordo però quali autorizzazioni siano necessarie.
Martin Smith,

1
L'avvio di un lavoro da un'altra procedura / database è un problema abbastanza complesso se non si desidera aprire grandi buchi di sicurezza. Erland Sommarskog ha un articolo sulle diverse tecniche che è necessario combinare: sommarskog.se/grantperm.html Tuttavia, non esiste una soluzione completa.
Sebastian Meine,

1

Un'altra possibilità sarebbe quella di ottenere la prima procedura memorizzata per scrivere su una tabella di controllo al termine e posizionare un trigger sulla tabella di controllo che avvia la seconda procedura memorizzata quando viene scritta la tabella di controllo. Non è necessario eseguire continuamente il polling e non è necessario un ulteriore processo di SQL Server Agent.


3
La prima procedura memorizzata non ritornerà fino al completamento dell'inserimento nella tabella di controllo e ciò non accadrà fino al completamento dell'esecuzione del trigger (inclusa la chiamata alla seconda procedura memorizzata)
Martin Smith

1
Ho già esaminato l'utilizzo di un trigger, ma i trigger vengono eseguiti in modo sincrono con l' istruzione INSERTo UPDATE, non in modo asincrono, quindi Martin ha ragione che la prima procedura finirebbe comunque ad aspettare fino al termine della seconda procedura.
Rachel,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.