Temos um procedimento armazenado que os usuários podem executar manualmente para obter alguns números atualizados para um relatório que é usado constantemente ao longo do dia.
Eu tenho um segundo procedimento armazenado que deve ser executado após a execução do primeiro procedimento armazenado, pois é baseado nos números obtidos desse primeiro procedimento armazenado, no entanto, leva mais tempo para ser executado e é para um processo separado, portanto, não quero faça o usuário esperar enquanto este segundo procedimento armazenado é executado.
Existe uma maneira de fazer com que um procedimento armazenado inicie um segundo procedimento armazenado e retorne imediatamente sem esperar pelos resultados?
Estou usando o SQL Server 2005.
Parece que existem várias maneiras de fazer isso, mas descobri que a maneira mais simples foi a sugestão de Martin de configurar o procedimento em um trabalho SQL e iniciá-lo usando o comando sp_start_job assíncrono do meu procedimento armazenado.
Isso só funciona para mim porque não preciso especificar nenhum parâmetro para meu procedimento armazenado.
Outras sugestões que podem funcionar dependendo da sua situação são
Usando o SQL Service Broker como Martin e Sebastian sugerem. Esta é provavelmente a melhor sugestão se você não se importar com a complexidade de configurá-lo e aprender como ele funciona.
Executando o processo de forma assíncrona no código que é responsável por executar o procedimento armazenado, como sugeriu Mr.Brownstone .
Não é uma má ideia, no entanto, no meu caso, o procedimento armazenado é chamado de vários lugares, portanto, encontrar todos esses lugares e garantir que eles chamem o segundo procedimento também não parece tão prático. Além disso, o segundo procedimento armazenado é bastante crítico e esquecer de executá-lo pode causar alguns problemas importantes para nossa empresa.
Faça o primeiro procedimento definir um sinalizador e configure um trabalho recorrente para verificar esse sinalizador e execute se estiver definido, como Jimbo sugeriu . Eu não sou um grande fã de trabalhos que são executados constantemente e verificam as alterações a cada poucos minutos, mas certamente é uma opção que vale a pena considerar dependendo da sua situação.
Esta velha questão merece uma resposta mais abrangente. Alguns deles são mencionados em outras respostas/comentários aqui, outros podem ou não funcionar para a situação específica do OP, mas podem funcionar para outros que procuram chamar procs armazenados de forma assíncrona do SQL.
Apenas para ser totalmente explícito: o TSQL não tem (por si só) a capacidade de iniciar outras operações TSQL de forma assíncrona .
Isso não significa que você ainda não tem muitas opções:
sp_start_job
. Se você precisar monitorar seu progresso programaticamente, apenas certifique-se de que cada trabalho atualize uma tabela JOB_PROGRESS personalizada (ou você pode verificar se eles já terminaram de usar a função não documentada,xp_sqlagent_enum_jobs
conforme descrito neste excelente artigo de Gregory A. Larsen). Você precisa criar quantos trabalhos separados quiser que os processos paralelos sejam executados, mesmo que estejam executando o mesmo procedimento armazenado com parâmetros diferentes.sp_oacreate
esp_oamethod
para iniciar um novo processo chamando um ao outro proc armazenado conforme descrito neste artigo , também por Gregory A. Larsen.Parallel_AddSql
eParallel_Execute
conforme descrito neste artigo por Alan Kaplan (somente SQL2005+).Se fosse eu, provavelmente usaria vários SQL Agent Jobs em cenários mais simples e um pacote SSIS em cenários mais complexos.
No seu caso, chamar trabalhos do SQL Agent parece uma escolha simples e gerenciável.
Um comentário final : SQL já tenta paralelizar operações individuais sempre que pode*. Isso significa que a execução de 2 tarefas ao mesmo tempo em vez de uma após a outra não é garantia de que terminará mais cedo. Teste cuidadosamente para ver se realmente melhora alguma coisa ou não.
Tivemos um desenvolvedor que criou um pacote DTS para executar 8 tarefas ao mesmo tempo. Infelizmente, era apenas um servidor de 4 CPUs :)
*Assumindo as configurações padrão. Isso pode ser modificado alterando o Grau Máximo de Paralelismo ou a Máscara de Afinidade do servidor ou usando a dica de consulta MAXDOP.
Você pode usar o service broker junto com a ativação na fila. Com isso você poderia postar os parâmetros para a chamada de procedimento na fila. Isso leva tanto tempo quanto uma inserção. Depois que a transação é confirmada e potencialmente mais alguns segundos, a ativação chamaria automaticamente o procedimento receptor de forma assíncrona. Não bastava pegar os parâmetros da fila e fazer o trabalho desejado.
Sim, um método:
Outra possibilidade seria obter o 1º procedimento armazenado para gravar em uma tabela de auditoria quando ele for concluído e colocar um gatilho na tabela de auditoria que inicia o 2º procedimento armazenado quando a tabela de auditoria é gravada. Não há necessidade de sondar continuamente e não há necessidade de um trabalho extra do SQL Server Agent.