A maioria dos administradores de banco de dados, independentemente da plataforma, está familiarizada com o conceito de eventos de espera. Os eventos de espera são uma parte natural de um mecanismo de banco de dados que processa solicitações. Quando uma conexão é feita para o mecanismo de banco de dados, uma identificação de sessão (SPID) é atribuída, o que permite que as solicitações sejam enviadas; muitas vezes as chamamos simplesmente de consultas.
Cada solicitação pode estar em um dos três estados possíveis: em execução, executável ou suspensa. Suspensa significa apenas que o SPID está aguardando um recurso, como uma página a ser lida do disco para a memória. Quando um SPID está suspenso, o motivo pelo qual ele está aguardando é registrado como um evento de espera. Executável significa que o SPID está aguardando um agendador disponível, geralmente chamado de processador ou CPU. “Em execução” quer dizer isso mesmo: o SPID está atualmente em execução.
Como bacharel em matemática, gosto de organizar as coisas em grupos. É por isso que, quando explico o conceito de eventos de espera, gosto de pensar neles em grupos. Já discutimos os primeiros: em execução, executável e suspenso. O próximo conjunto de grupos consiste nos próprios eventos de espera, que vou categorizar usando os seguintes nomes: esperas internas, por recursos e externas.
Vamos analisar o que cada um desses grupos significa para mim:
Esperas internas
As esperas internas são geralmente chamadas de travamento, bloqueio e deadlock. O motivo pelo qual o bloqueio, o travamento e o deadlock ocorrem é o isolamento da transação, uma configuração necessária para os bancos de dados relacionais, pois eles mantêm as propriedades de ACID de uma transação. Ao longo dos anos, tenho sido chamado para investigar problemas de desempenho e descobri que os usuários simplesmente experimentam os efeitos do nível de isolamento escolhido: o padrão para Microsoft® SQL Server® é LEITURA CONFIRMADA, e para o banco de dados do Microsoft Azure SQL, INSTANTÂNEO DE LEITURA CONFIRMADA.®
As diferenças nos níveis de isolamento podem afetar o desempenho e a taxa de transferência de aplicativos. Isso não significa que, ao perceber bloqueio e travamento, você deve alterar seu nível de isolamento de transação. Você precisa investigar por que o bloqueio está ocorrendo. O ponto que defendo aqui é que esse grupo de esperas internas (provavelmente) não será resolvido adicionando mais hardwares para tratar o problema. Embora seja possível que a causa raiz seja uma restrição de recursos (veja abaixo), é aconselhável investigar mudanças em seu código e esquema antes de gastar milhares de dólares em novo hardware para “corrigir” o bloqueio, o travamento ou o deadlock.
Esperas por recursos
Essas são as esperas mais comumente conhecidas que vimos ou sobre as quais ouvimos, com nomes como PAGEIOLATCH_EX ou CXPACKET. Elas são registradas quando uma sessão está na fila suspensa conforme descrito acima. Eu as agrupo como esperas por recursos porque elas são vinculadas a um dos quatro recursos de hardware físicos principais: CPU, memória, disco e rede.
Veja o que você precisa compreender sobre as esperas por recursos: só existem duas soluções possíveis. Em primeiro lugar, use menos. Em segundo lugar, compre mais. Considere, por exemplo, a memória física. Se você tivesse uma consulta que consumisse seu pool de buffers inteiro, causando problemas de desempenho para cerca de metade das consultas, você ajustaria a consulta ou adicionaria mais memória à instância. Quando você começa a pensar nas esperas por recursos dessa maneira, fica mais fácil decidir quais ações adotar para resolver um problema.
Esperas externas
Essas esperas são registradas quando uma sessão está em execução (!) e são facilmente identificadas porque os nomes de todas elas começam com a palavra PREEMPTIVE. Essas esperas são conhecidas como esperas não cooperativas, porque o SQL Server está sendo forçado a abandonar o controle da programação dessas tarefas. Muitas vezes, isso é o resultado da necessidade do SQL Server de fazer uma chamada externa (daí o nome do grupo) para o sistema operacional com vistas a algo como um procedimento armazenado externo ou o uso de objetos de SQL CLR. É interessante observar que, no que diz respeito ao SQL Server, a tarefa está em execução, mas o SQL Server não conhece o status da chamada remota. Isso torna difícil a solução de problemas dessas esperas.
Para complicar ainda mais as coisas, essas esperas não são muito bem documentadas. A melhor forma de pesquisar essas esperas é fazer uma pesquisa pelo nome da espera, mas remova “PREEMPTIVE”. Por exemplo, para o evento de espera PREEMPTIVE_OS_GETADDRINFO, vá para o Windows® Dev Center e pesquise GETADDRINFO.
Conclusão
Na minha opinião, pensar em grupos ajuda a chegar à causa raiz dos problemas de modo mais rápido. Quando se trata de eventos de espera, essa forma de pensar associada ao uso de ferramentas de análise baseadas em espera foi proveitosa para mim ao longo dos anos. No mesmo processo, como uma árvore de decisões, podemos usar o evento de espera, atribuí-lo a um grupo e, nele, conhecer as opções de otimização que temos. O resultado final é um uso eficiente de recursos para resolver o problema, mas, de forma mais importante, teremos um tempo menor para resolução dos problemas.
Thomas LaRock é Head Geek™, SolarWinds