ARQUITETURA SQL Server Parte 4: Execution Model



Pessoal primeiramente peço desculpas pela demora em postar coisas novas, o assunto deste post é mais delicado e acabei demorando mais tempo para escreve-lo, Execution Model do SQL Server, vamos começar pelas requisições para que fique explicado da melhor forma possível desde o começo!

Quando uma requisição de usuário é enviada ao SQL Server, conhecida como SPID ou SESSION_ID, é feito um controle sobre ela através do UMS (User Mode Scheduler), antes de falar sobre ele é importante manter em mente sobre as requisições que:


1. Uma conexão está mapeada para um sessão após o login (SPID ou SESSION_ID).

2. Cada sessão submete requisições (requests) para execução.

3. Cada requisição (ou batch) é mapeada para uma ou mais tarefas (tasks).

4. As tarefas (tasks) são submetidas para os schedulers para execução, com base no fator de carga.

5. No scheduler a tarefa é mapeada para um thread, e continua com esta thread (running, suspended, runnable) até que seja finalizada.


 Voltando ao UMS, este não substitui o scheduler do Windows, apenas garante que as threads submetidas para execução privilegiam o modelo de execução do SQL Server. 


Cada requisição (ou tarefa) é submetida para um UMS para execução e associada a uma thread. Formalmente, o UMS está associado a uma CPU específica apenas quando o affinity mask está definido. Existe um UMS (ou scheduler) para cada CPU visível para uma instância do SQL Server. O UMS é composto por algumas filas e listas, que são usadas para gerenciar as suas threads (workers) e requisições associadas. 


Cada UMS ira ter no máximo uma requisição executando, uma fila chamada de runnable queue, a qual mantem as requisições executando porém que já gastaram seu tempo na CPU e estão aguardando a mesma ficar disponível novamente para voltarem a efetivamente executar, uma lista chamada de waiter list, a qual armazena as requisições que aguardam por demais recursos, por exemplo, uma query com status RESOURCE_SEMAPHORE está aguardando um “grant” de memória, e por último, uma “work queue”, fila de requisições aguardando por worker threads. 
  
Cada worker thread está associado a uma thread do Windows e junto com outras, são agrupadas nos schedulers. O fluxo, resumidamente, seria mais ou menos o abaixo:
 
            Uma requisição rodando que precisa esperar por algo (disco por exemplo) é movida para a Wait Queue > Se houver alguma requisição na Runnable Queue ela será colocada para executar > As requisições da Wait Queue que já possuem os recursos para executar entram no final da Runnable Queue.


    Acredito que uma boa analogia seja um jogo de vôlei:


Imagine que o jogador na quadra está em “running” porem já esgotou suas forças (atingiu o quantum de CPU) e precisa descansar e então é substituído (enviado para a Runnable Queue), um jogador que estava fora mais que já havia jogado volta à quadra (sai da Runnable Queue), os jogadores que estavam se aquecendo já estão prontos para irem a quadra (saem da Waiter list) e esperam apenas o chamado do técnico (vão para o final da Runnable Queue).


Este mecanismo que fez nascer uma metodologia relacionada a tuning chamada de Waits and Queues, irei falar mais pra frente das esperas mais importantes, mais detalhes vocês também encontram no documento do link abaixo que também foi usado para a escrita deste post:





Outras referências: 


Livro Microsoft SQL Server 2008 Internals – Kalen Delaney



Qualquer dúvida estou à disposição pessoal! Um abraço!

Nenhum comentário:

Postar um comentário