Agendamento de tarefas ou lotes no SQL Server

Cada instância do SQL Server é um processo de sistema operacional separado. Cada instância deve lidar potencialmente com milhares de solicitações simultâneas de usuários. Instâncias do SQL Server usam threads do Microsoft Windows, ou se configuradas, usam fibras, para gerenciar bem essas tarefas simultâneas. Cada instância do SQL Server sempre executa vários threads de processos de sistema. Isso inclui um ou mais threads para cada servidor Net-Library, um thread de rede para lidar com a E/S de rede e um thread de sinal para comunicação com o Gerenciador de Controle de Serviços.

Compreendendo o agendamento

Cada instância do SQL Server tem uma camada interna que implementa um ambiente semelhante a um sistema operacional. Essa camada interna é usada para agendar e sincronizar tarefas simultâneas sem ter que chamar o kernel do Windows. Essa camada interna também pode agendar fibras ou threads do Windows com eficácia. Cada instância do SQL Server mantém um pool de fibras ou threads do Windows para processar consultas de usuário. O tamanho máximo desse pool é controlado pela opção de configuração de servidor max worker threads.

Para compreender como uma solicitação ou uma tarefa é processada, é útil compreender os seguintes termos básicos:

  • conexão
    Uma conexão é estabelecida quando o usuário faz logon com êxito. O usuário pode enviar uma ou mais instruções Transact-SQL para execução. Uma conexão é fechada quando o usuário faz logoff explicitamente ou a conexão é encerrada.

  • lote
    Um lote de SQL é um conjunto de uma ou mais instruções Transact-SQL enviado de um cliente para uma instância do SQL Server para execução. Ele representa uma unidade de trabalho enviada ao Mecanismo de Banco de Dados pelos usuários.

  • tarefa
    Uma tarefa representa uma unidade de trabalho agendada pelo SQL Server. Um lote pode ser mapeado para uma ou mais tarefas. Por exemplo, uma consulta paralela será executada por várias tarefas.

  • Thread do Windows
    Cada thread do Windows representa um mecanismo de execução independente.

  • fibra
    Uma fibra é um thread superficial que exige menos recursos do que um thread do Windows e pode alternar o contexto quando está no modo de usuário. Um thread do Windows pode ser mapeado para muitas fibras.

  • thread de trabalho
    O thread de trabalho representa um thread lógico no SQL Server que é mapeado internamente (1:1) para um thread do Windows ou, se o lightweight pooling estiver ATIVADO, para uma fibra. O mapeamento é mantido até o thread de trabalho ser desalocado devido à pressão da memória ou se ficar ocioso por muito tempo. A associação de uma tarefa a um thread de trabalho é mantida durante a execução da tarefa.

Gerenciando recursos de conexões de usuário e thread de trabalho

Mesmo que threads e fibras forem superficiais no uso de recursos, ainda consumirão recursos. Em sistemas com centenas ou milhares de conexões de usuário, ter um thread de trabalho por conexão pode consumir bastante recursos e reduzir a eficiência do SQL Server. Além disso, a alocação de um trabalho dedicado para cada conexão de usuário não é exigida, porque a maioria das conexões, na verdade, gasta grande parte do tempo esperando por lotes a serem recebidos do cliente. Em vez disso, a instância do SQL Server usa um pool de threads de trabalho. O pool de threads de trabalho só precisa ser grande o suficiente para atender o número de conexões de usuário que estão executando lotes ao mesmo tempo naquela instância. Deixar a opção max worker threads com o valor padrão 0 permite à instância do SQL Server mapear com eficácia conexões de usuário de vários threads de trabalho. Isso assegura que eles não consomem recursos demais.

Configurando SQL Server para fibras

A opção de configuração de servidor lightweight pooling controla se uma instância do SQL Server usa threads do Windows ou fibras. O padrão dessa opção é 0. Isso indica que a instância do SQL Server agenda um thread do Windows por thread de trabalho, até atingir o valor definido na opção max worker threads. Se o lightweight pooling for definido como 1, o SQL Server usará fibras em vez de threads do Windows. Isso é conhecido como execução em modo fibra. No modo fibra, uma instância do SQL Server aloca um thread do Windows por agendador de SQL e, depois, aloca uma fibra por thread de trabalho, até atingir o valor definido na opção max worker threads. Uma instância do SQL Server usa os mesmos algoritmos para agendar e sincronizar tarefas quando está usando os threads do Windows ou as fibras. O SQL Server Express não oferece suporte a fibras. Para obter mais informações, consulte Usando a opção lightweight pooling. Não recomendamos o uso de agendamento do modo fibra para operação rotineira. Isso porque ele pode diminuir o desempenho, inibindo os benefícios regulares de alternância de contexto, e porque alguns componentes do SQL Server não funcionam corretamente no modo fibra. Para obter mais informações, consulte lightweight pooling.

Como o agendamento de tarefas ou lote funciona

Quando um aplicativo é conectado ao Mecanismo de Banco de Dados, é atribuído um ID da sessão (SPID). Todas as informações que devem ser mantidas para a duração da conexão são gerenciadas em estruturas de dados internas associadas ao SPID. Conforme uma instância do SQL Server vai recebendo lotes de clientes, o lote é dividido em uma ou mais tarefas e, depois, cada tarefa é associada a um thread de trabalho disponível de um pool de threads de trabalho. Um thread de trabalho é associado a uma tarefa durante o tempo de vida da tarefa. Um thread de trabalho executa a solicitação no agendador de SQL associado. Se não houver threads de trabalho livres e o valor de max worker threads não for alcançado, a instância do SQL Server alocará um thread de trabalho novo para o lote novo. Se não houver threads ou fibras livres disponíveis e o valor de max worker threads tiver sido alcançado, a instância do SQL Server bloqueará a tarefa nova até um thread de trabalho ser liberado.

Depois que um trabalho for associado a uma tarefa, ele permanecerá associado à tarefa até ser concluído, por exemplo, até o último dos conjuntos de resultados gerados pelo lote ser retornado ao cliente. Naquele momento, o thread de trabalho é liberado e pode ser emparelhado com as tarefas associadas ao próximo lote.

O Mecanismo de Banco de Dados deve funcionar ativamente para uma conexão somente a partir do momento em que um lote é recebido até o momento em que os resultados são retornados ao cliente. Durante esse período, pode haver momentos em que o lote não exigirá processamento ativo. Por exemplo, pode haver momentos em que o Mecanismo de Banco de Dados deverá esperar por uma operação de leitura para recuperar os dados necessários para a consulta atual, ou esperar por outro lote para liberar um bloqueio. A tarefa para associação de trabalho é mantida até mesmo quando a tarefa é bloqueada em algum recurso.

Sempre que o Mecanismo de Banco de Dados começa a processar uma tarefa associada a um lote, ele agenda o thread de trabalho associado à tarefa para executar o trabalho. Depois que o thread de trabalho conclui o trabalho da tarefa, a instância do SQL Server despacha o thread de trabalho para a próxima tarefa que está pronta para funcionar. Um SPID permanece constante durante toda a conexão. Conexões longas podem ter as tarefas de lote individuais executadas por muitos threads de trabalho diferentes. Por exemplo, as tarefas do primeiro lote podem ser executadas pelo trabalho1, mas as tarefas do segundo lote podem ser executadas pelo trabalho2. Algumas instruções podem ser processadas em paralelo. Nesse caso, um lote pode ter várias tarefas executadas ao mesmo por vários threads de trabalho.