THE SQL TIMES

Respondendo os porquês sobre SQL Server, Windows, programação e outros assuntos sobre tecnologia

Um Generalista a mais no mercado?

Depois de um longo tempo sem postagem no blog, estou voltando aqui com algumas novidades. O tempo tem sido crucial, e muitas mudanças aconteceram em minha carreira e vida pessoal. Com isso acabei me afastando do blog. O post hoje conta um pouco do que aconteceu e o que espero pro ano de 2019!

 

Novos conhecimentos, mesmos meios

Depois de longos anos trabalhando com plataforma Microsoft, exclusivamente SQL Server e Windows, finalmente encarei a chance de conhecer outros produtos. Não um específico, mas diversos: o problema aparecia, e tinha que resolver.  Mysql, PostgreSQL, Oracle, DB2, sqlite, etc. Em um primeiro momento, acostumar com essas novas tecnologias é difícil, e chega até ser desanimador.  O SQL Server realmente é um produto incrível, e possui muitas features que tornam o dia-a-dia de um DBA muito mais fácil, porém nada básico. Possui uma engine poderosa, capaz de suportar os mais severos workloads, oriundos das mais exigentes aplicações do planeta. Por um outro lado, existem muitas features interessantes, e que até faltam no SQL Server.

Junto com o receio de se tornar um generalista, resolvi encarar o desafio. O resultado dessa experiência, conto um pouco a seguir.

A maior mudança: Linux

Sem dúvida, o maior conhecimento adquirido foi o Linux. Apesar de passar a maior parte do tempo em uma tela preta, sem usar mouse, diferente do Windows, isso não me trouxe limitação. A princípio, parece que aquilo é realmente uma caixa preta e qualquer mensagem significa o caos. Besteira. Um ambiente robusto, cheio  de controles, lógica, configurações, desafios. Nada diferente do Windows. Apenas um jeito diferente.

Aprender a usar Linux foi um dos, senão o maior, conhecimento que adquiri depois de aprender a programar e SQL Server. Eu não escondo para os meus colegas que sou fascinado pelo “internals” do SO, e o Linux me apresentou centenas de oportunidades para aprofundar mais esse conhecimento. Há quem diga que Windows é melhor, ou que Linux é melhor, ou ainda que Debian é melhor que CentOs, e vice-versa (feliz por entender agora o que esses termos significam). A velha história das comparações… Seguramente, posso dizer que é uma tremenda perda de tempo cair nessa discussão.

Hoje sou um apaixonado por bash, e meu velho powershell. Estou mesmo satisfeito por conhecer mais Linux, e poder explorar o melhor dos dois mundos. Agora, não importa se o problema é um pinguim adoecido, ou uma janela quebrada. Estarei aqui com as melhores ferramentas para resolvê-los.

 

Uma nova gama de opções de configuração e conceitos

Tive o prazer de atuar em problemas diversos em outras tecnologias de banco. Do mais simples aos mais complexos. Um dos meus primeiros desafios nos PostgreSQL foi apenas liberar o acesso de um usuário a partir de um novo IP.  Há um arquivo de configuração que você precisa editar pra isso. Aliás, é uma abordagem interessante. Diferente do SQL, há recursos nativos em outros bancos, como o PostgreSQL e no MySQL,  em que você consegue limitar o acesso do usuário a partir de um endereço. Realmente necessário? Uma discursão interessante pra uma conversa numa mesa de bar! 😆

Acostumar-se como o SQL Server instala seus binários, me fez ficar confuso com algumas tecnologias. Porém, comparar o conceito de instância do SQL Server, com os outros SGBDs, tornou as coisas mais claras no Oracle e no DB2.  No Oracle, o procedimento de instalação, reconhecido na comunidade técnica por ser “difícil”,  vai ficando mais claro a medida que você entende os conceitos. Muita coisa são apenas padrões, que, repassando de geração em geração, se torna um “é assim que se faz, pronto e acabou”. Cheguei até o ponto de criar novas instâncias Oracle manualmente, e me admirei com o fato que com apenas copiando alguns arquivos, você sobe uma “monstruosa” nova instância…  Minha dica é: entenda os conceitos de instância em “Oracle” e DB2 e você sairá vitorioso no primeiro contato com essas plataformas!

Planos de execução e Otimização de Queries

Uma das maiores causadoras de problemas em produção, a famosa lentidão de queries, não é exclusivo do SQL Server. Há sempre uma demanda para “pega as queries mais lenta e otimiza”. Essa nova jornada me trouxe um valioso conhecimento: Aprender a ler planos de execução no PostgreSQL, MySQL, etc. Sem muitas opções gráficas, me acostumei com a leitura do plano em texto.  A complexidade do Query Optimizer (QO) do SQL server deixou o caminho mais fácil para entender compreender o MySQL, que apesar de mais simples, toma decisões eficientes e inteligentes, que poupa trabalhos dos desenvolvedores. Porém, me ajudou a entender muito mais rápido os operadores do PostgreSQL, que possui uma gama infinita, com muito mais opções para controlar as decisões de seu otimizador, entretanto, com muita coisa semelhante do QO do SQL.

Num outro cenário, precisei avaliar o porquê de um simples banco no MySQL, em um portal de internet de um importante orgão do país, estava lento. Pra quem vem do SQL, é meio complicado lidar com a falta de uma sys.dm_exec_requests, ou sp_WhoIsActive. Mas, o meio de encontrar o problema é o mesmo: descubra a query, ou as queries lentas, e quais são seus gargalos. Aliado com as ferramentas do SO, conseguimos entender o problema, onde estava a limitação, e resolvemos isso usando recursos do Linux!

Também, apareceu uma chance incrível de operar um DB2, identificar locks, criar usuários, resolver gargalos, e até gerenciar uma replicação de dados!

Manipulação de Dados

Apareceu um desafio de auxiliar um processo de Auditoria de uma importante rede internacional de supermercados. Era necessário exportar conteúdo de um banco Oracle. Não tínhamos SSIS, nem interface gráfica. O desafio era tudo via linha de comando, era o que podia. Utilizamos a versão sqlcmd do oracle, o sqlplus. Com uma gama de opções, conseguimos exportar o conteúdo com sucesso.  O reconhecimento do vice-presidente desta empresa,  fez todo o esforço de usar powershell, para gerar um script bash que executava o sqlplus, valer a pena!

A triste e velha história da recuperação

Infelizmente, apesar de tantas diferenças, um problema comum: Recuperação. “O banco deu pau e não tem backup”.  Há quem diga que saber internals dos produtos é uma perda de tempo. Talvez sim, para aqueles que possuem recursos para suprir esse tipo de problema, ou mesmo que conseguem se convencer que tudo acabou nessas situações.

Além de conhecer novas formas, ferramentas e tipos de backup/restore (e em agluns casos, apenas diferente sintaxe, para os mesmos comandos), conseguir trabalhar em casos de recuperação de bancos sem backup.  Costurando bits, analisando logs, etc. Igual sempre foi no SQL nessas situações.  Alguns produtos apresentam uma comunidade forte, e documentação boa, outros nem tanto. A comunidade SQL Server realmente é um destaque quando se trata de conhecimentos mais avançados. Mas, é sensacional o fato de você poder ollhar no código-fonte do produto, gastar algumas horinhas apenas fazendo pesquisa de funções C++, entendedo as lógicas, em meios a poucos comentários de código.

 

Novos times

Uma das maiores  novidades, e, que, com muito orgulho, anuncio, foi a de entrar para o time da Fabrício Lima Soluções em Bancos de Dados.  O meu foco é o trabalho com SQL e Azure. Um time que já é muito forte e realmente tem sido animador. Além dos casos que aparecem, temos grupos de estudo, colocamos as experiências de todos para gerar soluções ótimas. É incrível o que esses caras fazem, e não é exagero a hashtag #AlwaysTunningYourData, porque é pra isso que todo esse conhecimento serve: pra fazer com que o seu SQL Server voe, seguindo as melhores e mais eficientes práticas.

Uma oportunidade que, chegou em um momento em que eu estava me distanciando do operacional de banco de dados, na Stefanini. Tendendo para automações de ações e serviços da infraestrutura, exigência da própria Adminstração de Banco de Dados, cheguei em uma equipe de inovação. Aqui aprendi python, docker(e já entrando em kubernetes), serviços cognitivos, machine learning, etc. Uma incrível oportunidade em um momento que todo o mundo já se volta para essas tecnologias!

Realmente tenho muito orgulho dos times que faço parte hoje. Ambos se beneficam das experiências adquiridas em cada um, e me apoiam. Isso faz toda diferença e realmente estou muito empolgado para 2019!

 

Na realidade, nada novo…

Apesar dessas novidades,  a essência não mudou. Ainda continuo apaixonado por assuntos de tecnologia, e gasto horas tentando entender os porquês. Se aparece um problema, seja com python, seja com sql no linux, sql no docker, db2 em Windows, eu passo algumas horas analisando cada log, cada mensagem, juntando as peças, consultando informações, abrindo ferramentas de monitoramento e trace. Tudo está interligado. Cada conhecimento em uma tecnologia, cada forma de resolver o problema, preenche uma vasta biblioteca na minha cabeça (e no meu OneNote,  Dropbox, etc.) com tudo que preciso para resolver os problemas.

E é nisso que se tem se resumindo meu dia-a-dia. Continuo sim, atuando em bancos de dados, especialmente na infraestrutura, resolvendo diretamente casos críticos ou discutindo com uma equipe como resolver. Continuo abrindo o Process Explorer, mas agora abro htop, ps ou top também. Ainda, nos casos mais bizarros, abro o Process Monitor, mas também abro o strace agora. Mais do que nunca tenho brincando com o Windbg ( e ainda não abrir um debugger no Linux, mas estamos quase lá  :-D). Leio internals de Windows, e também já lí o incrível Kernel Development do Linux. E também frequentemente consulto o código-fonte para tirar algumas dúvidas (uma delas, foi auxiliar no entendimento do “Load Average”).

Espero trazer mais em 2019 (e nesse finalzinho de 2018 também)! Mostrar como usar ferramentas, explicar conceitos, etc. Tudo o que já vinha escrito neste blog, porém com mais gama de experiência, tecnologias e ferramentas! E então, será que eu me tornei mesmo um Generalista? Não! Ainda estou envolvido com tecnologias específicas! Mas, estou acompanhando a TI, e indo com as novidades, levando tudo que aprendi até hoje para esse mundo! E tem dado certo, muito certo!

Pra fechar, novamente, a imagem que abre esse post: reflete o que foi esses meus 9 anos na área de TI, retirado da minha palestra no SQL Saturday 811:

 

Kernel Mode vs User Mode

Aprofundar o conhecimento em um software, requer entender muitas características do sistema operacional. No caso de SO’s como o Windows, é comum, em cursos avançados ouvir as expressões “Kernel Mode” e “User Mode”. Com o intuito de fazer um rápido esclarecimento sobre o que significam estes nomes, eu preparei este post.

Certas áreas de memória contém dados vitais para o correto funcionamento do Windows. Por exemplo, imagine que no endereço  0xFFFF0000, o Windows guardasse a quantidade total de memória livre para alocação. Ora, se uma thread qualquer  altera esse valor, o Windows poderia achar que havia mais ou menos memória disponível para alocação. Isso traria instabilidade e incosistência para todo o sistema operacional, e, consequentemente, todos os processos em execução.

Para se prevenir deste tipo de caso, e outros, o Windows fornece privilégios que permitem ou impedem que uma thread acesse um determinado recurso, como certos endereços de memória. Na verdade, isso é possível graças ao processador: Nos primeiros momentos do boot, ele está livre e sem restrições, então o sistema operacional interage com ele e registra uma série de rotinas e códigos necessários para serem executados quando certos eventos ocorrem durante as execuções das instruções. Alguns destes eventos são disparados justamente quando uma thread necessita acessar algum recurso protegido. Diante disso, o processador irá executar o código que o sistema operacional registrou e o mesmo irá tratar de forma adequada o acesso. No exemplo acima, ao acessar o endereço de memória crítico, o Windows irá impedir a ação de ser executada e gerar um erro para a thread que tentou fazer o acesso.

Mas não é todo momento que uma thread deve ser impedida de acessar recursos críticos. Por exemplo, ao realizar um leitura de arquivo, a thread necessita chamar a função “ReadFile”, da API do Windows. Essa função vai executar um código que requer o acesso a estruturas protegidas pelo sistema operacional. Neste caso, se houver o impedimento por parte do sistema operacinal, a thread não irá conseguir efetuar a leitura do arquivo.

Para resolver isso, o Windows define dois modos de operação das threads:

  • User Mode
    O User Mode é o modo de operação em que as threads executam na maior parte do tempo. Neste modo, a thread não pode acessar recursos vitais para o funcionamento do sistema, como certos endereços de memória e registradores. Para acessar, é necessário entrar no “Kernel Mode”.
  • Kernel Mode
    Este é o modo sob o qual as threads que executam o código do sistema operam, já que o mesmo referencia estruturas internas para completar os serviços oferecidos. A API do Windows contém funções que executam instruções que fazem com que o sistema entre neste modo. Um leitor curioso, pode então, concluir que seria fácil burlar as proteções do Kernel Mode, bastando apenas executar esta instruções que ativam o Kernel Mode. Bom, não é bem assim.

Transição User Mode – Kernel Mode

Quando a thread executa a instrução que faz o modo de operação mudar para Kernel Mode, o processador interrompe a execução da mesma e passa o controle para umas dessas rotinas que o Windows registrou lá no boot. Isso significa, que graças ao suporte que o processador oferece, a thread passa a rodar um código confiável pelo Windows, isto é, que faz parte do kernel. Dessa maneira, ela deixa de executar o seu código original, e passa a executar um código específico para tratar este evento gerado pelo processador. O nome da instrução que solicita essa transição depende da arquitetura e família do processador. No caso de processadores Intel x64, o nome da instrução é syscall (Fonte: Intel® 64 and IA-32 Architectures, Página 1788). Esse processo tambem é conhecido como “uso dos serviços do sistema operacional”, pois é assim que um processo consegue interagir com as centenas de rotinas (os chamados “serviços”) que provê alguma funcionalidade do Windows (como ler arquivos, criar processos, transferir dados via rede, etc.).

Mesmo que o usuário utilizasse a instrução syscall em seu código diretamente, o código do sistema tomaria o controle da execução e impediria o usuário de realizar qualquer modificação que não fosse por parte de um código criado pelos desenvolvedores do Windows.

É comum observar nas literaturas a respeito da arquitetura do Windows, o fato de que a API do Windows possui uma parte User Mode e uma parte Kernel Mode. Utilizar a instrução syscall diretamente seria chato e complexo para os desenvolvedores. Ao realizar a transição para Kernel Mode, é necessário informar uma série de parâmetros (via registradores da CPU), que o código do Windows irá validar para determinar o que deverá ser feito a partir dali. Ao invés do desenvolvedor ter que decorar as centenas de códigos que são definidos, o Windows disponibiliza uma série de funções em DLLs como “kernel32.dll” e “user32.dll”. Essa funções são responsáveis por preparar os parâmetros e executar a instrução “syscall”.  Então, por isso, até que a instrução “syscall” seja executada, o código da DLL que faz parte do Windows, ainda estava rodando em User Mode, isto é, se houvesse uma tentativa de acessar um recurso protegido nesse momento, haveria uma falha (o que seria um bug no sistema operacional, já que a DLL faz parte do Windows). Por exemplo, a função ReadFile é definida na DLL “Kernel32.dll” (Fonte: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365467%28v=vs.85%29.aspx). Essa é a função que deve ser usada sempre que um processo necessita ler um arquivo (ou uma de suas variações, como ReadFileEx). O SQL Server faz uso dessa função para ler o conteúdo dos arquivos de dados e log. Ao iniciar a sua execução, a função irá realizar todas as validações necessárias e irá executar outras funções que estão defindias em outras DLLs do Windows. E são essas funções que irão preparar e executar a instrução syscall.

Transição Kernel Mode – User Mode

Depois que o código do sistema operacional termina seu trabalho, é necessário retomar a execução do código original, isto é, o codigo que causou a transição para Kernel Mode. Mas antes, é necessário voltar ao User Mode, caso contrário, toda o esquema de proteção feito até aqui seria inútil.  Assim como existem instruções para entrar em Kernel Mode, existem para sair. De novo, o nome vai depender da família e arquitetura do processador. No caso de x64 , a instrução é a sysret ( Fonte: Intel® 64 and IA-32 Architectures, Página 1796  ). Quando o código do sistema operacional termina de fazer o que lhe foi solicitado, então ele executa a instrução sysret, saindo do Kernel Mode e retomando a execução do código após o syscall que causou a transição para Kernel Mode.

Mais alguns comentários…

 

Antes de encerrar, é importante fortalecer alguns pontos.

  1. Tudo isso foi um resumo do resumo da resenha do rascunho do que é realmente o Kernel Mode e o User Mode, e como ocorre toda essas transições. Se você quer se aprofundar no assunto, pode usar a referência que deixei no final do artigo (e, se ainda não o fez, aproveita para estudar C++ e Assembly, pois vai facilitar o entendimento de muita coisa).
  2. User Mode e Kernel Mode não são threads ou processos diferentes. Uma thread pode em um determinado momento estar em User Mode, e um outro determinado momento em Kernel Mode. O que muda é que em Kernel Mode ela estara executando um código do sistema operacional ou driver. Isso indica que se a thread passa muito tempo em Kernel Mode, é uma grande chance de ser um problema de hardware, uso intenso de recursos do SO ou bug do sistema (este último com chances bem menores, mas não impossível).

    Vida da thread e modos de operação

  3. Algumas ferramentas, como o gerenciador de tarefas e o Process Explorer, permite que você monitore o uso de CPU em Kernel Mode. Por exemplo, você consegue determinar quanto de tempo foi gasto pelas threads executando em Kernel Mode.

    O gráfico em vermelho mostra o tempo gasto pela CPU executando instruções sob o modo Kernel Mode. Também, é possivel obter informações por processo. Na imagem, é possível observar o texto “Kernel Time” na janela da direita. Esta informação indica o tempo total gasto em Kernel Mode pelo processo. O mesmo vale pro “User Time”.

  4. O que tudo isso tem a ver com SQL Server? Não somente com SQL Server, mas com qualquer software que rode no Windows. Todos eles fazem uso constante de serviços do sistema. Assim, entender o que é o Kernel Mode é útil para determinar se um possível problema está no sistema operacional ou no software. A transição para Kernel Mode é algo muito custoso do ponto de vista de um processo. Envolve a execução de mais algumas centenas instruções, acesso a memória, recursos compartilhados, etc. O SQL Server foi desenvolvido para evitar ao máximo fazer transições de User Mode para Kernel Mode, para salvar a perfomance. É obvio que existem casos onde não é possivel evitar isso, como no momento em que é necessário ler ou escrever dos arquivos. Mas é sempre bom estar de olho nas métricas relativo ao uso dos recursos em Kernel Mode.

 

Referências:

 

After SQLServerDF XXXIII: SQL Server CPU Foundations

Na última quarta-feira (29/06/2016) tive a oportunidade de apresentar o tema que gosto bastante: CPU. A apresentação “SQL Server: CPU Foundations” foi bem legal e apesar de ter falhado em umas das demos, gostei bastante.

Os scripts podem ser baixados no link https://drive.google.com/open?id=0B9MFBfb3HCHXNG9TM2pwcW1ILTg

A demo que falhou

Há uma demo nesta apresentação cujo o objetivo é demonstrar como é possível ter valores de CPU acima de 100%. Nesta demo, o SQL Server é configurado para rodar somente nas CPUs 2 e 3, além de abrir duas sessões que executam uma query que causa o uso de 100% de CPU.  O que se espera é ver o processo do SQL Server consumindo duas CPUs em 100%, uma em cada sessão, e causando os 200% de CPU no perfmon.

Porém, ao realizar esta demonstração, o SQL Server jogava as sessões apenas em uma CPU. Após analisar esse comportamento com mais calma, eu notei um detalhe que havia esquecido de considerar ao realizá-la: Os schedulers. Os schedulers são uma espécie de porta para a CPU. O SQL Server usa os schedulers para gerenciar a  execução de suas tarefas (workers, pra ser mais exato).  Toda tarefa tem um scheduler associado.  Baseado em alguns fatores, dentre eles, a carga do schedulers (quantas tarefas já estão “alocadas” no scheduler), o SQL Server escolhe em qual scheduler a task vai rodar.  Se duas tasks estão configuradas para rodar no mesmo scheduler, então, essas tasks podem acabar na mesma CPU.

E era isso o que ocorreu na demonstração. Os scripts acima contém os detalhes de como reproduzir a demo que falhou e contornar quando o SQL Server tentar alocar as duas conexões no mesmo scheduler.

 

Obrigado!

 

[]’s
Rodrigo Ribeiro Gomes

After SQL Server CPU Foundations – DevSQL #SQLSat512

Olá!

No dia 12/05/2016 fiz uma apresentação para o chapter DevSQL, como parte de uma prévia para o evento SQL Saturday #512, que irá acontecer dia 18/06/2016, no Rio de Janeiro!

Os arquivos da apresentação estão disponíveis neste link e incluem:

  • Os scripts usados nas demonstrações
  • O PDF da apresentação, contendo diversas notas semelhantes ao que foi falado
  • O PPS para reproduzir a apresentação, permitindo reproduzir as animações

Gravação: Houve um problema com a gravação, mas a última informação que tenho é que foi gravado da metade para a frente. Quando houver novas informações eu atualizo o post.

Mais uma vez agradeço a todos que reservaram um tempo do seu dia para assistir a apresentação. Se você tiver dúvidas, pode postar nos comentários.

Ah, se você quiser, pode avaliar a apresentação deixando seu feedback aqui neste formulário. Sua opinião sempre será bem vinda!