@03 – O que Acontece?

No 3º post da sessão O que Acontece. Você vai conhecer um pouco sobre Storage Engine, Armazenamento e Lazy Writer, componentes e tarefas existentes no Microsoft SQL Server, envolvidos diretamente na leitura e acesso a dados.

Bom dia!

Feliz 2021, estamos abrindo os trabalhos deste ano em meu blog, como mais um novo post da sessão O que acontece.

Seja bem-vindo ao @03 – O que Acontece? 

Seguindo as tradição, antes de apresentar o terceiro post, quero destacar alguns pontos sobre esta sessão, em especial o tipo de conteúdo que você leitor vai encontrar em cada post relacionado a ela:

1 – Os posts publicados nesta sessão envolvem um pouco do Micrososft SQL Server, na verdade o objetivo dela é tentar mostrar como ele SQL Server, o qual aqui eu vou denominar como caixa, pensa exclusivamente fora dela, ou seja, como este grandioso SGBD (Sistema Gerenciador de Banco de Dados) faz para que tenhamos nossos dados armazenados e apresentados em tela, em adicional como podemos de uma forma simples aprender, conhecer, desvendar os comportamentos realizados por ele além do uso das habituais ferramentas de administração: SQL Server Management Studio ou Azure Data Studio.

2 – Os posts, não apresentam o objetivo de demonstrar recursos, comandos, funcionalidades ou ensinar algo novo, na verdade eu quero tentar mostrar o que acontece muitas vezes quando por exemplo você esta processando um simples comando Select buscando milhões de dados em uma tabela, e o SQL Server Management Studio vai apresentando aos poucos os registros. Serão exclusivamente estes cenários, comportamentos e formas de atuação envolvendo o SQL Server e o ambiente que ele se encontra;

3 – Os posts, não terão uma estrutura padrão, na verdade, O que Acontece, foi idealizado da mesma forma que inicialmente começamos a pensar. Vamos reunindo conhecimentos, ideias, possibilidades, hipóteses, analisando alternativas, mensurando teorias, até tentar construir algo mais concreto;

4 – Não será estabelecido um calendário de publicação, ao contrário, sempre que algum pensamento fora da caixa pairar sobre a minha cabeça, ou coisas do meu dia-a-dia relacionados as minhas experiências profissionais ou acadêmicas, novos posts serão publicados, bem como, os atuais atualizados e corrigidos;

5 – Não vou me ater ao certo ou errado, melhor ou pior, tecnicamente perfeito ou melhor tecnicamente, o que eu quero é tentar como eu já destaquei ilustrar o que acontece do lado de fora do SQL Server, o que ele muitas vezes esta realizando e não temos ideia do que está acontecendo; e

6 – Vou tentar em cada post trazer uma ferramenta, aplicativo ou utilitário existente no próprio sistema operacional que possa nos ajudar a observar e entender o que está acontecendo de preferência em tempo real, em adicional, se possível utilizarei vídeos para elucidar de forma mais didática o objetivo do post.

Vamos começar nossa aventura.

Seja mais uma vez bem-vindo ao @03 – O que Acontece – O processo de leitura de dados através de uma aplicação C#!

Pensar no conteúdo de um novo post de acordo com sua respectiva sessão não é uma atividade que posso considerar como algo simples ou fácil, idealizar o conteúdo, imaginar o que pode ser compartilhado requer uma certa imaginação, o que eu não vejo ser muito bom em fazer, mas eu procuro tentar.

Como sempre, de uma hora para outra a minha mente começa a juntar um pouco do conhecimento, experiência e pensamentos meio loucos para se tentar contextualizar mesmo que de forma vaga um rascunho, e hoje não foi diferente, acordei como de costume bem cedinho e pensei na possibilidade de mostrar o que acontece quando realizamos um dos procedimentos mais comuns dentro de uma aplicação desenvolvida através da Linguagem C#, a  ação de realizar a “leitura de dados através desta aplicação” conectada ao Microsoft SQL Server.

Neste momento estava surgindo o terceiro post da sessão O que Acontece.

Linguagem C#

Uma das mais conhecidas Linguagens de Programação Orientada a Objetos,  desenvolvida pela Microsoft, que faz parte da plataforma .NET.

Embora a linguagem C# tenha sido criada do zero, foi baseada na linguagem C++ e tem muitos elementos da linguagem Pascal e Java.

A plataforma .NET teve suas bibliotecas inicialmente feitas em Simple Managed C (SMC), porém esta limitou muito o trabalho na plataforma. No início de 1999 foi montada uma equipe, liderada por Anders Hejlsberg, com o objetivo de criar uma nova linguagem para a plataforma .NET, esta linguagem seria criada para desprender a plataforma .NET de outras linguagens, pois o código das linguagens já existentes limitava o desenvolvimento da plataforma.

A linguagem C# foi desenvolvida com o nome de Cool. No momento do lançamento da plataforma .NET, mudaram o nome da linguagem para C#, sua criação ajudou muito no desenvolvimento do .NET, pois a plataforma não precisou se adequar a nenhum código de alguma linguagem já existente. A mesma foi criada especificamente para a plataforma .NET, mesmo assim, muitas outras linguagens tem suporte á C#, entre elas: VB.NET, C++ e J#.

No entanto, a linguagem C# venha a ser considerada muito semelhante ao Java, existem varias diferenças:

  • Java não tem a função de implementar propriedades nem sobrecarga de operadores, o C# tem esta função;
  • Java não tem a função de implementar um modo inseguro que pode ser utilizado para manipulação de ponteiros e aritmética sem checagem. Esta função é característica do C#;
  • Java possui as exceções checadas, enquanto as exceções em C# não são checadas (assim como em C++);
  • Enquanto Java utiliza comentários Javadoc para gerar documentação automática, O C# Utiliza o XML; e
  • C# tem suporte à indexadores, e o Java não.

STorage Engine

Reconhecido como um componentes mais complexos que formam o grande ambiente do Microsoft SQL Server. Para muitos é o principal componente, ao lado do Engine Relacional, dentro do SQL Server.

Apesar de o Storage Engine e o Relational Engine serem totalmente independentes, eles interagem entre si, tendo como base os componentes de acesso nativo, como o OLE DB.

Dentre as várias responsabilidades, existem alguns de extrema importância desempenhadas pelo Storage Engine, dentre as quais destaco:

  • Gerenciar o armazenamento dos dados em discos e todo o IO (input/output) necessário para acesso a essa estrutura;
  • Armazenar e gerenciar as estruturas físicas dos objetos, utilizando blocos, como páginas;
  • Prover a capacidade de manter dados em uma estrutura de memória, chamada de buffer, ou cache;
  • Controlar concorrência;
  • Gerenciar transações e locks;
  • Recuperar os dados em caso de falhas; e
  • Manter os demais dados acessíveis mesmo em situações de falha, dentro das possibilidades de acesso.

O ARmazenamento

Semelhante a outras plataformas de Bancos de Dados Relacionais (Relationships Databases), o Microsoft SQL Server possui uma estrutura de memória, parte do Storage Engine, conhecida como Buffer Pool, ou Buffer Cache.

A qual é responsável em armazenar as páginas de memória de 8k (8 kilobytes), o tamanho utilizado, por padrão no SQL Server, para armazenamento nossos dados existentes nas respectivas tabelas e índices.

As páginas de 8k são armazenadas fisicamente nos arquivos de dados, os .mdf e .ndf, em grupos de 8 páginas, a estrutura de 8 páginas de 8k é denominada extents, formando uma estrutura com tamanho total de 64k.

O Microsoft SQL Server faz uso de extents para otimizar as leituras e escritas para ler e escrever mais dados ao invés de apenas 8k, porém algumas operações fazem especificamente IOs (inputs e outputs) de 8k, por lidarem com páginas específicas.

Pois bem, agora que você já conhece um pouco sobre os principais componentes envolvidos neste post, nada melhor que saber ouo melhor ver o que acontece de forma conceitual, quando nossa aplicação realiza o processo de leitura dos dados.


Chegou a hora de ver então o que acontece…..

Para esta aventura não será necessário criar nenhum ambiente, vamos conhecer um pouco sobre os conceitos, imaginando o comportamento de forma prática, iniciando pelo processo da Leitura dos Dados, e um dos comportamentos padrões durante o acesso aos nossos dados, chamado de Lazy Writer.

A leitura dos dados

Quando efetuamos uma leitura a partir de uma aplicação desenvolvida através da linguagem C#, de forma básica estamos fazendo uso do conjunto de recursos e funcionalidades disponibilizadas por esta linguagem para nossa aplicação, o que podemos entender como as bibliotecas ou arquivos .dll, responsáveis em estabelecer o fluxo natural entre a aplicação e o Microsoft SQL Server, organizado da seguinte forma:

1 – Nossa aplicação se conecta ao SQL Server através da camada de Protocolos e sua consulta deve obrigatoriamente passar pela Engine Relacional.

2 – O Relational Engine então faz a validação, ou Parse da Query, e durante o processo de otimização gera um Plano de Execução para esta consulta. Este plano então é armazenado numa área de memória, conhecida como Plan Cache para otimizar as próximas execuções desta query.

3 – Este plano de execução gerado pela Engine Relacional serve como um mapa para que o próximo componente, o Storage Engine, seja capaz de buscar os dados solicitados da melhor forma possível, caso seja possível.

4 – Ao longo do processo de otimização, o otimizador de queries não escolhe necessariamente o melhor plano mas sim um plano bom o suciente para a execução da Query, na decorrência de tentar implementar a forma mais simples, evitando ao máximo o gasto no tempo de processamento.

5 – Tendo o plano já defindo o Storage Engine poderá realizar as tarefas necessárias para buscar os dados que suas consultas solicitaram, de forma tradicional aguardando  o Storage Engine na tentativa de buscar nossos dados em seu próprio cache, ou seja, o Buffer Pool (área de memória).

Importante: Todas as consultas passam obrigatoriamente por essa área de memória. Caso as páginas de dados que possuem os dados que você precisa estejam em memória (nesta área de cache), a sua consulta pode ser retornada com sucesso. Sem a necessidade de ler seus arquivos físicos, esse tipo de leitura, em memória, é muito mais rápida, é o que chamamos de leitura lógica ou logical read.

6 – Ao identificar que os dados solicitados não encontram-se neste momento no Buffer Pool, o Storage Engine toma outra decisão importante, inicia-se então a leitura em disco, nos arquivos de dados, buscando pela informação que você está procurando, obviamente levando em conta o plano de execução, ou o mapa, por assim dizer, que foi passado para ele pela Engine Relacional. É neste respectivo momento, após o IO em disco ser efetuado, que o Storage Engine armazena as páginas lidas no Buffer Pool para que possa otimizar as próximas leituras que solicitarem as mesmas páginas.

Importante: Todas as tarefas de acesso e armazenamento de dados de forma física e lógica é realizada e gerenciada pelo Storage Engine, nenhum outro componente existente no Microsoft SQL Server tem este poder.

7 – Agora com os dados alocados em memória, ou seja, na área de Cache, neste caso o Buffer Pool, o SQL Server não precisa mais realizar uma leitura Física e, nesse caso, ele realiza, apenas a Leitura Lógica contidos nas respectivas áreas de buffer.

Lazy Writer (A coleta seletiva)

O Buffer Pool, conhecido como a área de memória que comporta as páginas dos seus bancos de dados é limitada, sendo assim, a ocorrência de situações que necessitam alocar mais dados em memória do que se encontra disponível é algo comum de se acontecer, é justamente neste cenário que poderá ocorrer a presença do chamado Lazy Writer.

Afim de tentar ajudar o nosso entendimento, gostaria de propor um cenário imaginário: Pense no seu ambiente de banco de dados, o qual neste momento apresenta uma área de memória em um determinado servidor com a capacidade de alocar 8GBs e você já está utilizando efetivamente um total de 7.6GB.

O que poderia acontecer se uma nova leitura de 600Mb ocorresse?

Para tentar responder este pergunta, é importante conhecermos o SQLOs (SQL Server Operation System – Sistema Operacional do Microsoft SQL Server), isso mesmo, eu não estou louco não, o SQL Server possui seu próprio Sistema Operacional.

O SQLOS representado pela Figura 1 a seguir, conhecido como o sistema operacional do SQL Server, através de um dos seus componentes internos, chamado Resource Monitor, em tempo real identifica que uma pressão interna de memória está ocorrendo, afinal, 400Mb não são suficientes para acomodar os 600Mb solicitados pela nossa aplicação:

Figura 1 – Representação da Arquitetura do SQLOS.

A partir deste monitoramento, o Resource Monitor, envia uma notificação para que esse pequeno problema de memória no Buffer Pool seja tratado por um agente de gerenciamento de recurso, ou uma tarefa interna.

O tal “agente” ou tarefa interna, responsável por gerenciar a memória do Buffer Pool é chamado de Lazy Writer. É então que o nosso amigo Lazy Write entra em acesso, realizando a importante tarefa de limpar o cache páginas sujas, ou seja, páginas que já foram modificadas e já estão salvas em disco, nos seus arquivos de dados. 

Observação: Eu particularmente gosto de dizer para os meus alunos e clientes, que o Lazy Writer é a tarefa de coleta seletiva existente no Microsoft SQL Server.

Mas você pode estar se perguntando, ou até mesmo pensando. O Lazy Writer não esta realizando a mesma tarefa do CheckPoint?
A resposta é simples e direta, não, estas tarefas ou comportamentos existentes no Microsoft SQL Server são bem diferentes.

CHECKPOINT

É uma das tarefas mais importantes existentes dentro do ambiente do Microsoft SQL Server. Sua responsabilidade é escrever as páginas que foram modificadas no Buffer Pool para os arquivos de dados, mas o CHECKPOINT não necessariamente remove as páginas dessas áreas de cache, na verdade, a quantidade de dados em memória não diminui após a execução de um CHECKPOINT.

Mas este é assunto para outro post.

Voltando a falar do Lazy Writer.  A limpeza da área de cache realizada por ele, acontece através do de um algoritmo denominado LRU2 (Least Recently Used), em suma, as páginas de dados mais antigas, ou as que foram utilizadas menos recentemente, são marcadas como disponíveis para serem reutilizadas por outras alocações.

Neste caso no cenário imaginado anteriormente, mesmo tendo disponível somente 400Mbs de memória RAM, outros 200Mbs estarão disponíveis para serem utilizado, em forma de páginas marcadas como disponíveis, pois as mesmas identificadas como limpas dentro do Buffer Pool existente naquele momento, o qual foi trabalhado pelo Lazy Writer. As referidas páginas deixam de existir em memória, porém ainda estão em disco, uma vez que o SQL Server deve garantir a persistência dos dados.

Na ocorrência de um nova leitura de dados por parte da nossa aplicação, ou qualquer outro recurso, será realizada uma nova busca por estes dados, que estão alocados em suas respectivas páginas que acabaram de ser removidas do Buffer Pool.

Para este cenário não será realizada apenas as leituras lógicas, como seria feito quando as mesmas páginas que ainda estavam presentes em memória, torna-se necessário realizar as leituras física nos arquivos de dados em que as páginas se encontram.


Desta forma, chegamos ao final do @03 – O que Acontece –  O processo de leitura de dados através de uma aplicação C#!

Espero que este conteúdo conceitual possa ser útil, o qual teve o objetivo de destacar o que acontece quando nossas aplicações, em especial desenvolvidas na linguagem C# realizando a leitura de dados armazenados no Microsoft SQL Server.

De forma simples e básica, forma destacados alguns dos componentes mais importantes existentes no SQL Server, dentre eles: Storage Engine, Buffer Pool e Buffer Cache, em adicional as tarefas de Lazy Writer e Checkpoint foram brevemente abordadas.

E aí gostou deste post? Espero que sim.


Mais uma vez obrigado por sua visita, aproveite para acessar as outras sessões existentes no meu blog.

Um forte abraço.

Autor: Junior Galvão - MVP

Profissional com vasta experiência na área de Tecnologia da Informação e soluções Microsoft. Pós-Graduado no Curso de Gestão e Engenharia de Processos para Desenvolvimento de Software com RUP na Faculdade FIAP – Faculdade de Informática e Administração Paulista de São Paulo. Graduado no Curso Superior em Gestão da Tecnologia de Sistemas de Informação pela Uninove – Campus São Roque. Formação MCDBA Microsoft, autor de artigos acadêmicos e profissionais postados em Revistas, Instituições de Ensino e WebSistes. Meu primeiro contato com tecnologia ocorreu em 1994 após meus pais comprarem nosso primeiro computador, ano em que as portas para este fantástico mundo se abriram. Neste mesmo ano, comecei o de Processamento de Dados, naquele momento a palavra TI não existia, na verdade a Tecnologia da Informação era conhecida como Computação ou Informática, foi assim que tudo começou e desde então não parei mais, continuando nesta longa estrada até hoje. Desde 2001 tenho atuado como Database Administrator – Administrador de Banco de Dados – SQL Server em tarefas de Administração, Gerenciamento, Migração de Servidores e Bancos de Dados, Estratégias de Backup/Restauração, Replicação, LogShipping, Implantação de ERPs que utilizam bancos SQL Server, Desenvolvimento de Funções, Stored Procedure, entre outros recursos. Desde 2008 exerço a função de Professor Universitário, para as disciplinas de Banco de Dados, Administração, Modelagem de Banco de Dados, Programação em Banco de Dados, Sistemas Operacionais, Análise e Projetos de Sistemas, entre outras. Experiência na Coordenação de Projetos de Alta Disponibilidade de Dados, utilizando Database Mirroring, Replicação Transacional e Merge, Log Shipping, etc. Trabalhei entre 2011 e 2017 como Administrador de Banco de Dados e Coordenador de TI no FIT – Instituto de Tecnologia da Flextronics, atualmente exerço a função de Professor Universitário na FATEC São Roque. CTO da Galvão Tecnologia, consultoria especializada em Gestão de TI, Administração de Servidores Windows Server, Bancos de Dados Microsoft SQL Server e Virtualização. Possuo titulação Oficial Microsoft MVP e reconhecimentos: MCC, MSTC, MIE e MTAC.