Eu tenho uma situação em que vários aplicativos cliente enviam mensagens por meio do Service Broker (utilizando procedimentos armazenados). Essas mensagens são captadas por outro aplicativo cliente e processadas. A forma como as mensagens são captadas é que o aplicativo emite a seguinte instrução SQL (pseudocódigo):
LOOP {
WAITFOR (RECEIVE CONVERT(int, message_body) AS Message FROM SB_ReceiveQ)
ProcessMessage
}
Então, basicamente, o código é bloqueado até que uma mensagem seja recebida. Isso tudo funciona bem.
Minha pergunta é sobre a implicação de emitir um WAITFOR (RECEIVE...
comando que paira sobre algum recurso baseado no corretor de serviços basicamente para sempre. Há algum problema de desempenho associado a esse padrão que eu deva saber?
Para referência, este é o SQL Server 2005.
Você está bloqueando um worker no SQL Server e os workers são limitados, sujeitos ao máximo de threads de worker . Isso significa que não deve haver milhares de solicitações bloqueadas
WAITFOR(RECEIVE...)
ou você deixará de trabalhar no servidor.Mas a primeira pergunta que vem à mente é : Por que não aproveitar a Ativação do Service Broker ? Desta forma, você não estaria esperando o tempo todo, mas apenas quando ativado porque há mensagens para receber.
Temos mais de 50 máquinas fazendo isso o dia todo, todos os dias no SQL Server 2005. Faz mais de 3 anos sem problemas.
O maior problema que conheço com um indefinido
WAITFOR
é a expansão do arquivo de log. Isso é descrito aqui . O SQL Server conecta-se a seu log quando você inicia uma transação. Todos os eventos transacionais, comoUPDATE
s para outras tabelas, que acontecerem após o início da transação serão registrados no log “depois” disso. Pode-se pensar na escrita do SQL Server no arquivo de log de forma circular: quando chega ao fim, vai para o início e continua. No entanto, uma vez que o log é preenchido com “transações ativas” não recuperáveis, ele deve começar a expandir o log, se ativado.Expandir o arquivo de log é caro. Se o servidor precisar registrar coisas antes de poder responder aos clientes, essas respostas terão que esperar que o registro se expanda. Além disso, se as transações durarem para sempre, o log será expandido até usar todo o espaço livre disponível.
Contanto que sua
RECEIVE
execução demore, isso impedirá a recuperação do log. Você pode atenuar isso garantindo que seuRECEIVE
tempo limite seja curto o suficiente para evitar que o log cresça indefinidamente e manuseie a condição de erro de um evento que não chega a tempo para o tempo limite.