Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Sugiro que você leia a transcrição do relatório do início de 2016 de Andrey Salnikov “Erros típicos em aplicativos que levam ao inchaço no postgresql”

Neste relatório, analisarei os principais erros em aplicações que surgem na fase de projeto e escrita do código da aplicação. E considerarei apenas os erros que levam ao inchaço no Postgresql. Via de regra, este é o começo do fim do desempenho do seu sistema como um todo, embora inicialmente nenhum pré-requisito para isso fosse visível.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Fico feliz em receber a todos! Este relatório não é tão técnico como o anterior do meu colega. Este relatório destina-se principalmente a desenvolvedores de sistemas back-end porque temos um número bastante grande de clientes. E todos cometem os mesmos erros. Eu vou te contar sobre eles. Explicarei a que coisas fatais e ruins esses erros levam.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Por que os erros são cometidos? São feitos por dois motivos: ao acaso, talvez dê certo, e por desconhecimento de alguns mecanismos que ocorrem no nível entre o banco de dados e a aplicação, bem como no próprio banco de dados.

Vou dar três exemplos com imagens terríveis de como as coisas ficaram ruins. Vou falar brevemente sobre o mecanismo que acontece lá. E como lidar com eles, quando aconteceram e quais métodos preventivos usar para evitar erros. Vou falar sobre as ferramentas auxiliares e fornecer links úteis.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Usei um banco de dados de teste onde tinha duas tabelas. Uma placa com contas de clientes, outra com transações nessas contas. E com certa frequência atualizamos os saldos dessas contas.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Dados iniciais da placa: é bem pequeno, 2 MB. O tempo de resposta do banco de dados e especificamente da sinalização também é muito bom. E uma carga bastante boa - 2 operações por segundo de acordo com a placa.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

E através deste relatório vou mostrar gráficos para que vocês entendam claramente o que está acontecendo. Sempre haverá 2 slides com gráficos. O primeiro slide é o que acontece em geral no servidor.

E nesta situação vemos que realmente temos um pequeno sinal. O índice é pequeno, 2 MB. Este é o primeiro gráfico à esquerda.

O tempo médio de resposta no servidor também é estável e curto. Este é o gráfico superior direito.

O gráfico inferior esquerdo mostra as transações mais longas. Vemos que as transações são concluídas rapidamente. E o autovácuo aqui ainda não funciona, porque foi um teste inicial. Continuará a funcionar e será útil para nós.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

O segundo slide será sempre dedicado à placa que está sendo testada. Nesta situação, atualizamos constantemente os saldos das contas dos clientes. E vemos que o tempo médio de resposta para uma operação de atualização é bastante bom, menos de um milissegundo. Vemos que os recursos do processador (este é o gráfico superior direito) também são consumidos de maneira uniforme e bastante pequena.

O gráfico inferior direito mostra quanta memória operacional e de disco utilizamos em busca da linha desejada antes de atualizá-la. E o número de operações de acordo com o sinal é 2 por segundo, como falei no início.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

E agora temos uma tragédia. Por alguma razão, há uma transação há muito esquecida. Os motivos costumam ser todos banais:

  • Uma das mais comuns é que passamos a acessar um serviço externo no código da aplicação. E este serviço não nos atende. Ou seja, abrimos uma transação, fizemos uma alteração no banco de dados e passamos do aplicativo para leitura de mail ou para outro serviço da nossa infraestrutura, e por algum motivo ele não nos responde. E nossa sessão está presa em um estado onde não se sabe quando será resolvida.
  • A segunda situação é quando ocorre uma exceção em nosso código por algum motivo. E na exceção não processamos o fechamento da transação. E terminamos com uma sessão suspensa com uma transação aberta.
  • E o último também é um caso bastante comum. Este é um código de baixa qualidade. Algumas estruturas abrem uma transação. Ele trava e você pode não saber no aplicativo que o está travando.

Aonde essas coisas levam?

A ponto de nossas tabelas e índices começarem a aumentar dramaticamente. Este é exatamente o mesmo efeito de inchaço. Para o banco de dados, isso significará que o tempo de resposta do banco de dados aumentará muito e a carga no servidor de banco de dados aumentará. E como resultado, nosso aplicativo sofrerá. Porque se você gastou 10 milissegundos em seu código em uma solicitação ao banco de dados, 10 milissegundos em sua lógica, então sua função levou 20 milissegundos para ser concluída. E agora sua situação será muito triste.

E vamos ver o que acontece. O gráfico inferior esquerdo mostra que temos uma transação longa e longa. E se olharmos para o gráfico superior esquerdo, vemos que o tamanho da nossa tabela saltou repentinamente de dois megabytes para 300 megabytes. Ao mesmo tempo, a quantidade de dados na tabela não mudou, ou seja, há uma quantidade bastante grande de lixo lá.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

A situação geral relativa ao tempo médio de resposta do servidor também mudou em várias ordens de grandeza. Ou seja, todas as solicitações no servidor começaram a cair completamente. E, ao mesmo tempo, foram lançados processos internos do Postgres na forma de autovacuum, que tentam fazer alguma coisa e consomem recursos.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

O que está acontecendo com nosso signo? O mesmo. Nosso tempo médio de resposta de acordo com o sinal aumentou várias ordens de grandeza. Especificamente em termos de recursos consumidos, vemos que a carga do processador aumentou muito. Este é o gráfico superior direito. E aumentou porque o processador tem que vasculhar um monte de linhas inúteis em busca da que precisa. Este é o gráfico inferior direito. E com isso, nosso número de chamadas por segundo começou a cair significativamente, pois o banco de dados não tinha tempo para processar o mesmo número de solicitações.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Precisamos voltar à vida. Entramos na Internet e descobrimos que transações longas levam a problemas. Encontramos e eliminamos esta transação. E tudo está se tornando normal para nós. Tudo funciona como deveria.

Nos acalmamos, mas depois de um tempo começamos a perceber que o aplicativo não funciona da mesma forma que antes da emergência. As solicitações ainda são processadas de forma mais lenta e significativamente mais lenta. Uma vez e meia a duas vezes mais lento, especificamente no meu exemplo. A carga no servidor também está maior do que antes do acidente.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

E a pergunta: “O que está acontecendo com a base neste momento?” E a seguinte situação ocorre com a base. No gráfico de transações você pode ver que ela parou e realmente não há transações de longo prazo. Mas o tamanho da placa aumentou fatalmente durante o acidente. E desde então eles não diminuíram. O tempo médio na base se estabilizou. E as respostas parecem estar chegando de forma adequada e a uma velocidade aceitável para nós. O autovacuum ficou mais ativo e começou a fazer alguma coisa com a placa, pois precisa filtrar mais dados.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Especificamente, de acordo com a placa de teste com contas, onde alteramos os saldos: o tempo de resposta a uma solicitação parece ter voltado ao normal. Mas, na realidade, é uma vez e meia maior.

E pela carga no processador, vemos que a carga no processador não retornou ao valor exigido antes da falha. E as razões residem precisamente no gráfico inferior direito. Pode-se observar que uma certa quantidade de memória está sendo pesquisada ali. Ou seja, para encontrar a linha necessária, desperdiçamos os recursos do servidor de banco de dados enquanto classificamos os dados inúteis. O número de transações por segundo se estabilizou.

No geral bom, mas a situação é pior do que era. Degradação clara do banco de dados como consequência de nossa aplicação que funciona com este banco de dados.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

E para entender o que está acontecendo aí, se você não estava no relatório anterior, agora vamos fazer um pouco de teoria. Teoria sobre o processo interno. Por que um aspirador de carro e o que ele faz?

Literalmente brevemente para compreensão. Em algum momento temos uma mesa. Temos linhas na tabela. Essas linhas podem ser ativas, vivas e o que precisamos agora. Eles estão marcados em verde na imagem. E há prazos que já foram acertados, foram atualizados e surgiram novos lançamentos sobre eles. E estão marcados que não são mais interessantes para o banco de dados. Mas eles estão na tabela devido a um recurso do Postgres.

Por que você precisa de um aspirador de carro? Em algum momento, o autovacuum chega, acessa o banco de dados e pergunta: “Por favor, me dê o id da transação mais antiga que está atualmente aberta no banco de dados”. O banco de dados retorna esse ID. E o autovacuum, contando com ele, classifica as linhas da tabela. E se ele perceber que algumas linhas foram alteradas por transações muito mais antigas, então ele tem o direito de marcá-las como linhas que podemos reutilizar no futuro, gravando novos dados ali. Este é um processo em segundo plano.

Neste momento, continuamos trabalhando com o banco de dados e fazendo algumas alterações na tabela. E nestas linhas, que podemos reutilizar, escrevemos novos dados. E assim obtemos um ciclo, ou seja, sempre aparecem algumas linhas antigas e mortas ali, em vez delas anotamos novas linhas que precisamos. E este é um estado normal para o funcionamento do PostgreSQL.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

O que aconteceu durante o acidente? Como aconteceu esse processo lá?

Tínhamos uma placa em algumas condições, algumas ao vivo, algumas com prazo final. O aspirador de carro chegou. Ele perguntou ao banco de dados qual é a nossa transação mais antiga e qual é o seu id. Recebi esta identificação, que pode ter sido há muitas horas, talvez dez minutos atrás. Depende de quão pesada é a carga que você tem em seu banco de dados. E foi em busca de linhas que pudesse marcar como reutilizadas. E não encontrei essas linhas em nossa tabela.

Mas neste momento continuamos trabalhando com a mesa. Fazemos algo nele, atualizamos, alteramos os dados. O que o banco de dados deve fazer neste momento? Ela não tem escolha senão adicionar novas linhas ao final da tabela existente. E assim o tamanho da nossa mesa começa a aumentar.

Na realidade, precisamos de linhas verdes para funcionar. Mas durante esse problema, verifica-se que a porcentagem de linhas verdes é extremamente baixa em toda a tabela.

E quando executamos uma consulta, o banco de dados tem que percorrer todas as linhas: tanto vermelha quanto verde, para encontrar a linha desejada. E o efeito de inchar uma tabela com dados inúteis é chamado de “inchaço”, que também consome nosso espaço em disco. Lembra, eram 2 MB, passou para 300 MB? Agora mude megabytes para gigabytes e você perderá rapidamente todos os recursos do disco.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Que consequências poderão haver para nós?

  • No meu exemplo, a tabela e o índice cresceram 150 vezes. Alguns de nossos clientes tiveram casos mais fatais quando simplesmente começaram a ficar sem espaço em disco.
  • O tamanho das tabelas em si nunca diminuirá. O vácuo automático, em alguns casos, pode cortar a ponta da mesa se houver apenas prazos. Mas como há rotação constante, uma linha verde pode congelar no final e não ser atualizada, enquanto todas as outras serão escritas em algum lugar no início da placa. Mas este é um evento tão improvável que sua própria mesa diminuirá de tamanho, então você não deve esperar por isso.
  • O banco de dados precisa classificar um monte de linhas inúteis. E desperdiçamos recursos de disco, desperdiçamos recursos de processador e eletricidade.
  • E isso afeta diretamente a nossa aplicação, pois se no início gastamos 10 milissegundos na solicitação, 10 milissegundos no nosso código, então durante o travamento começamos a gastar um segundo na solicitação e 10 milissegundos no código, ou seja, uma ordem de magnitude no desempenho do aplicativo diminuiu. E quando o acidente foi resolvido, começamos a gastar 20 milissegundos em uma solicitação, 10 milissegundos em um código. Isso significa que ainda caímos uma vez e meia na produtividade. E tudo isso por causa de uma transação que travou, talvez por nossa culpa.
  • E a pergunta: “Como podemos recuperar tudo?” para que tudo fique bem conosco e os pedidos cheguem tão rapidamente quanto antes do acidente.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Para isso existe um determinado ciclo de trabalho que é realizado.

Primeiro precisamos encontrar as tabelas problemáticas que estão inchadas. Entendemos que em algumas tabelas a gravação é mais ativa, em outras menos ativa. E para isso usamos a extensão pgstattuple. Ao instalar esta extensão, você pode escrever consultas que o ajudarão a encontrar tabelas bastante inchadas.

Depois de encontrar essas tabelas, você precisa compactá-las. Já existem ferramentas para isso. Em nossa empresa usamos três ferramentas. O primeiro é o VACUUM FULL integrado. Ele é cruel, duro e impiedoso, mas às vezes é muito útil. Pg_repack и pgcompacttable - Estes são utilitários de terceiros para compactação de tabelas. E tratam o banco de dados com mais cuidado.

Eles são usados ​​dependendo do que for mais conveniente para você. Mas vou falar sobre isso no final. O principal é que existem três ferramentas. Há muito por onde escolher.

Depois de corrigirmos tudo e nos certificarmos de que está tudo bem, devemos saber como evitar esta situação no futuro:

  • Isso pode ser evitado facilmente. Você precisa monitorar a duração das sessões no servidor Master. Sessões especialmente perigosas em modo inativo no estado de transação. São aqueles que acabaram de abrir uma transação, fizeram alguma coisa e saíram, ou simplesmente travaram, se perderam no código.
  • E para vocês, como desenvolvedores, é importante testar seu código quando essas situações surgirem. Não é difícil de fazer. Esta será uma verificação útil. Você evitará um grande número de problemas “infantis” associados a transações longas.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Nestes gráficos, eu queria mostrar como o sinal e o comportamento do banco de dados mudaram depois que passei pelo sinal com VACUUM FULL neste caso. Isso não é produção para mim.

O tamanho da tabela retornou imediatamente ao seu estado operacional normal de alguns megabytes. Isso não afetou muito o tempo médio de resposta do servidor.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Mas especificamente para o nosso sinal de teste, onde atualizamos os saldos das contas, vemos que o tempo médio de resposta para uma solicitação de atualização de dados no sinal foi reduzido para níveis pré-emergenciais. Os recursos consumidos pelo processador para concluir esta solicitação também caíram para níveis anteriores à falha. E o gráfico inferior direito mostra que agora encontramos exatamente a linha que precisamos imediatamente, sem passar pelas pilhas de linhas mortas que estavam lá antes da tabela ser compactada. E o tempo médio de solicitação permaneceu aproximadamente no mesmo nível. Mas aqui tenho, sim, um erro no meu hardware.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

É aqui que termina a primeira história. É o mais comum. E isso acontece com todos, independente da experiência do cliente e da qualificação dos programadores. Mais cedo ou mais tarde isso acontece.

A segunda história, em que distribuímos a carga e otimizamos os recursos do servidor

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

  • Já crescemos e nos tornamos caras sérios. E entendemos que temos uma réplica e seria bom equilibrarmos a carga: escrever no Master e ler na réplica. E normalmente esta situação surge quando queremos preparar alguns relatórios ou ETL. E os negócios estão muito felizes com isso. Ele realmente deseja uma variedade de relatórios com muitas análises complexas.
  • Os relatórios levam muitas horas, porque análises complexas não podem ser calculadas em milissegundos. Nós, como caras corajosos, escrevemos código. Na aplicação de inserção fazemos a gravação no Master, e executamos os relatórios na réplica.
  • Distribuindo a carga.
  • Tudo funciona perfeitamente. Eram ótimos.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

E como é essa situação? Especificamente nesses gráficos, também adicionei a duração das transações da réplica à duração da transação. Todos os outros gráficos referem-se apenas ao servidor Master.

A essa altura, meu quadro de relatórios havia crescido. Existem mais deles. Vemos que o tempo médio de resposta do servidor é estável. Vemos que na réplica temos uma transação de longa duração que dura 2 horas. Vemos o funcionamento silencioso do autovacuum, que processa prazos. E está tudo bem conosco.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Especificamente, de acordo com a placa testada, continuamos atualizando os saldos das contas por lá. E também temos um tempo de resposta estável para solicitações, consumo estável de recursos. Está tudo bem conosco.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Tudo está bem até o momento em que esses relatórios começam a responder devido a um conflito com a replicação. E eles disparam de volta em intervalos regulares.

Entramos na Internet e começamos a ler por que isso está acontecendo. E encontramos uma solução.

A primeira solução é aumentar a latência de replicação. Sabemos que nosso relatório dura 3 horas. Definimos o atraso de replicação para 3 horas. Estamos lançando tudo, mas ainda continuamos tendo problemas com relatórios que às vezes são cancelados.

Queremos que tudo seja perfeito. Subimos mais. E encontramos uma configuração legal na Internet - hot_standby_feedback. Vamos ligá-lo. Hot_standby_feedback nos permite reter o autovacuum no Master. Assim, nos livramos completamente dos conflitos de replicação. E tudo funciona bem para nós com relatórios.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

E o que está acontecendo com o servidor Master neste momento? E estamos com problemas totais com o servidor Master. Agora estamos vendo os gráficos quando tenho essas duas configurações habilitadas. E vemos que a sessão em nossa réplica de alguma forma começou a influenciar a situação no servidor Master. Ela tem efeito porque pausou o vácuo automático, o que elimina os prazos. O tamanho da nossa mesa disparou novamente. O tempo médio de execução de consultas em todo o banco de dados também disparou. Os autoaspiradores ficaram um pouco mais tensos.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Especificamente, pela nossa placa, vemos que a atualização dos dados também saltou para o céu. O consumo de CPU também aumentou bastante. Estamos novamente passando por um grande número de linhas mortas e inúteis. E o tempo de resposta para esse sinal e o número de transações caíram.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Como será se não soubermos do que eu estava falando antes?

  • Começamos a procurar problemas. Se encontramos problemas na primeira parte, sabemos que isso pode ser devido a uma longa transação e vamos ao Master. Temos um problema com o Mestre. Salsichas para ele. Aquece, sua média de carga é de cerca de cem.
  • As solicitações são lentas, mas não vemos nenhuma transação de longa duração. E não entendemos qual é o problema. Não entendemos onde procurar.
  • Verificamos o equipamento do servidor. Talvez nosso ataque tenha falhado. Talvez nosso cartão de memória esteja queimado. Sim, tudo pode acontecer. Mas não, os servidores são novos, tudo funciona bem.
  • Todos estão correndo: administradores, desenvolvedores e o diretor. Nada ajuda.
  • E em algum momento tudo de repente começa a se corrigir.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Neste momento, a solicitação em nossa réplica foi processada e deixada. Recebemos o relatório. Os negócios ainda estão felizes. Como você pode ver, nosso letreiro voltou a crescer e não vai diminuir. No gráfico com sessões deixei um pedaço dessa longa transação de uma réplica para que vocês possam estimar quanto tempo leva até que a situação se estabilize.

A sessão acabou. E só depois de algum tempo o servidor fica mais ou menos em ordem. E o tempo médio de resposta das solicitações no servidor Master volta ao normal. Porque, finalmente, o autovácuo tem a oportunidade de limpar e marcar esses prazos. E ele começou a fazer seu trabalho. E com que rapidez ele faz isso, tão rapidamente entraremos em ordem.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

De acordo com o tablet testado, onde atualizamos os saldos das contas, vemos exatamente a mesma imagem. O tempo médio de atualização da conta também está se normalizando gradualmente. Os recursos consumidos pelo processador também são reduzidos. E o número de transações por segundo volta ao normal. Mas novamente voltamos ao normal, não como éramos antes do acidente.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Em qualquer caso, obtemos uma redução no desempenho, como no primeiro caso, de uma vez e meia a duas vezes, e às vezes mais.

Parece que fizemos tudo certo. Distribua a carga. O equipamento não está ocioso. Dividimos os pedidos de acordo com a nossa vontade, mas mesmo assim tudo deu errado.

  • Não habilite hot_standby_feedback? Sim, não é recomendado ligá-lo sem motivos particularmente fortes. Porque essa reviravolta afeta diretamente o servidor Master e suspende o funcionamento do autovacuum ali. Ao habilitá-lo em alguma réplica e esquecê-lo, você pode matar o Master e ter grandes problemas com o aplicativo.
  • Aumentar max_standby_streaming_delay? Sim, para relatórios isso é verdade. Se você tiver um relatório de três horas e não quiser que ele trave devido a conflitos de replicação, basta aumentar o atraso. Um relatório de longo prazo nunca requer dados que chegaram ao banco de dados no momento. Se você o tiver por três horas, estará executando-o por algum período de dados antigos. E para você, se há um atraso de três horas ou um atraso de seis horas não fará diferença, mas você receberá relatórios de forma consistente e não terá problemas com eles caindo.
  • Naturalmente, você precisa controlar sessões longas em réplicas, especialmente se decidir habilitar hot_standby_feedback em uma réplica. Porque tudo pode acontecer. Entregamos essa réplica ao desenvolvedor para que ele pudesse testar as solicitações. Ele escreveu um pedido maluco. Ele lançou e saiu para tomar chá, e pegamos o Mestre estabelecido. Ou talvez tenhamos colocado o aplicativo errado lá. As situações são variadas. As sessões nas réplicas devem ser monitoradas com o mesmo cuidado que no Master.
  • E se você tiver consultas rápidas e longas nas réplicas, nesse caso é melhor dividi-las para distribuir a carga. Este é um link para streaming_delay. Para os mais rápidos, tenha uma réplica com um pequeno atraso de replicação. Para solicitações de relatórios de longa duração, tenha uma réplica que possa atrasar 6 horas ou um dia. Esta é uma situação completamente normal.

Eliminamos as consequências da mesma forma:

  • Encontramos mesas inchadas.
  • E nós o compactamos com a ferramenta mais conveniente que nos convém.

A segunda história termina aqui. Vamos para a terceira história.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Também bastante comum para nós, onde fazemos migração.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

  • Qualquer produto de software está crescendo. Os requisitos para isso estão mudando. De qualquer forma, queremos evoluir. E acontece que precisamos de atualizar os dados da tabela, nomeadamente para fazer uma atualização ao nível da nossa migração para a nova funcionalidade que estamos a introduzir no âmbito do nosso desenvolvimento.
  • O antigo formato de dados não é satisfatório. Digamos que agora vamos para a segunda tabela, onde tenho as transações nessas contas. E digamos que estavam em rublos e decidimos aumentar a precisão e fazê-lo em copeques. E para isso precisamos fazer uma atualização: multiplicar o campo com o valor da transação por cem.
  • No mundo de hoje, usamos ferramentas automatizadas de controle de versão de banco de dados. Digamos Liquibase. Registramos nossa migração lá. Nós testamos em nossa base de testes. Tudo está bem. A atualização está em andamento. Bloqueia o trabalho por um tempo, mas obtemos dados atualizados. E podemos lançar novas funcionalidades sobre isso. Tudo foi testado e verificado. Tudo foi confirmado.
  • Realizamos trabalhos planejados e realizamos migração.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Aqui está a migração com a atualização apresentada à sua frente. Como essas são transações da minha conta, a placa era de 15 GB. E como atualizamos cada linha, dobramos o tamanho da tabela com a atualização, porque reescrevemos cada linha.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Durante a migração, não pudemos fazer nada com esta placa, pois todas as solicitações para ela ficaram na fila e aguardamos até que esta atualização fosse concluída. Mas aqui quero chamar a atenção para os números que estão no eixo vertical. Ou seja, temos um tempo médio de solicitação antes da migração de cerca de 5 milissegundos e a carga do processador, o número de operações de bloco para leitura da memória do disco é inferior a 7,5.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Realizamos a migração e voltamos a ter problemas.

A migração foi bem-sucedida, mas:

  • A funcionalidade antiga agora leva mais tempo para ser concluída.
  • A mesa cresceu novamente de tamanho.
  • A carga no servidor tornou-se novamente maior do que antes.
  • E, claro, ainda estamos mexendo na funcionalidade que funcionou bem, melhoramos um pouco.

E isso é novamente um inchaço que novamente arruína nossas vidas.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Aqui demonstro que a tabela, assim como os dois casos anteriores, não vai voltar aos tamanhos anteriores. A carga média do servidor parece adequada.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

E se nos voltarmos para a tabela com contas, veremos que o tempo médio de solicitação desta tabela dobrou. A carga do processador e o número de linhas organizadas na memória saltaram acima de 7,5, mas foram menores. E saltou 2 vezes no caso dos processadores, 1,5 vezes no caso das operações em bloco, ou seja, tivemos uma degradação no desempenho do servidor. E como resultado - degradação do desempenho do nosso aplicativo. Ao mesmo tempo, o número de chamadas manteve-se aproximadamente no mesmo nível.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

E o principal aqui é entender como fazer essas migrações corretamente. E eles precisam ser feitos. Fazemos essas migrações de forma bastante consistente.

  • Essas grandes migrações não acontecem automaticamente. Eles devem estar sempre sob controle.
  • É necessária a supervisão de uma pessoa experiente. Se você tem um DBA em sua equipe, deixe o DBA fazer isso. É o trabalho dele. Caso contrário, deixe que faça isso a pessoa mais experiente, que sabe trabalhar com bancos de dados.
  • Um novo esquema de banco de dados, mesmo que atualizemos uma coluna, sempre preparamos em etapas, ou seja, com antecedência, antes que a nova versão do aplicativo seja lançada:
  • Novos campos são adicionados nos quais registraremos os dados atualizados.
  • Transferimos dados do campo antigo para o novo em pequenas partes. Por que estamos fazendo isso? Em primeiro lugar, sempre controlamos o andamento desse processo. Sabemos que já transferimos tantos lotes e ainda restam tantos.
  • E o segundo efeito positivo é que entre cada lote fechamos a transação, abrimos um novo, e isso permite que o autovacuum funcione de acordo com a placa, marque prazos para reaproveitamento.
  • Para as linhas que aparecerão enquanto a aplicação estiver em execução (ainda temos a aplicação antiga em execução), adicionamos um gatilho que grava novos valores em novos campos. No nosso caso, isso é uma multiplicação por cem do valor antigo.
  • Se formos completamente teimosos e quisermos o mesmo campo, após a conclusão de todas as migrações e antes de lançar uma nova versão do aplicativo, simplesmente renomeamos os campos. Os antigos recebem algum nome inventado e os novos campos são renomeados para os antigos.
  • E só depois lançamos uma nova versão do aplicativo.

E ao mesmo tempo não teremos inchaço e não sofreremos em termos de desempenho.

É aqui que termina a terceira história.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

https://github.com/dataegret/pg-utils/blob/master/sql/table_bloat.sql

https://github.com/dataegret/pg-utils/blob/master/sql/table_bloat_approx.sql

E agora um pouco mais de detalhes sobre as ferramentas que mencionei na primeira história.

Antes de procurar inchaço, você deve instalar a extensão pgstattuple.

Para que você não precise fazer perguntas, já escrevemos essas perguntas em nosso trabalho. Você pode usá-los. Existem dois pedidos aqui.

  • O primeiro leva muito tempo para funcionar, mas mostrará os valores exatos de inchaço da tabela.
  • O segundo funciona mais rápido e é muito eficaz quando você precisa avaliar rapidamente se há inchaço ou não de acordo com a tabela. E você também deve entender que o inchaço está sempre presente em uma tabela do Postgres. Esta é uma característica do seu modelo MVCC.
  • E o inchaço de 20% é normal para mesas na maioria dos casos. Ou seja, você não deve se preocupar e compactar esta tabela.

Descobrimos como identificar tabelas que estão cheias de dados inúteis.

Agora sobre como consertar o inchaço:

  • Se tivermos um tablet pequeno e bons discos, ou seja, em um tablet de até um gigabyte, é bem possível usar o VACUUM FULL. Ele vai pegar um cadeado exclusivo seu na mesa por alguns segundos e tudo bem, mas fará tudo de forma rápida e dura. O que o VÁCUO COMPLETO faz? É necessário um bloqueio exclusivo na tabela e reescreve as linhas ativas das tabelas antigas na nova tabela. E no final ele os substitui. Ele exclui arquivos antigos e substitui os antigos por novos. Mas durante o seu trabalho, ele ocupa um cadeado exclusivo na mesa. Isso significa que você não pode fazer nada com esta tabela: nem escrever nela, nem ler nela, nem modificá-la. E VACUUM FULL requer espaço adicional em disco para gravar dados.
  • Próxima ferramenta pg_repack. Em seu princípio, é muito semelhante ao VACUUM FULL, pois também reescreve dados de arquivos antigos para novos e os substitui na tabela. Mas, ao mesmo tempo, não faz um bloqueio exclusivo na tabela logo no início de seu trabalho, mas apenas no momento em que já possui os dados prontos para substituir os arquivos. Seus requisitos de recursos de disco são semelhantes aos do VACUUM FULL. Você precisa de espaço em disco adicional e isso às vezes é crítico se você tiver tabelas de terabytes. E consome bastante processador porque funciona ativamente com E/S.
  • A terceira utilidade é pgcompacttable. É mais cuidadoso com os recursos porque funciona segundo princípios ligeiramente diferentes. A ideia principal do pgcompacttable é mover todas as linhas ativas para o início da tabela usando atualizações na tabela. E então ele cria um vácuo nesta tabela, porque sabemos que temos linhas ativas no início e linhas mortas no final. E o próprio vácuo corta essa cauda, ​​ou seja, não requer muito espaço adicional em disco. E, ao mesmo tempo, ainda pode ser espremido em termos de recursos.

Tudo com ferramentas.

Erros típicos em aplicativos que levam ao inchaço no postgresql. Andrey Salnikov

Se você achar o tópico inchado interessante em termos de aprofundamento, aqui estão alguns links úteis:

Tentei mais mostrar uma história de terror para os desenvolvedores, pois eles são nossos clientes diretos dos bancos de dados e devem entender o que e a que ações levam. Espero ter conseguido. Obrigado pela sua atenção!

perguntas

Obrigado pelo relatório! Você falou sobre como você pode identificar problemas. Como eles podem ser avisados? Ou seja, tive uma situação em que as solicitações travaram não só porque acessaram alguns serviços externos. Estas foram apenas algumas junções selvagens. Houve alguns pedidos minúsculos e inofensivos que ficaram por um dia e depois começaram a fazer algumas bobagens. Ou seja, muito parecido com o que você descreve. Como rastrear isso? Sente-se e observe constantemente qual solicitação está travada? Como isto pode ser evitado?

Neste caso, esta é uma tarefa dos administradores da sua empresa, não necessariamente do DBA.

Eu sou um administrador.

O PostgreSQL possui uma visualização chamada pg_stat_activity que mostra consultas pendentes. E você pode ver quanto tempo fica lá.

Tenho que entrar e olhar a cada 5 minutos?

Configure o cron e verifique. Se você tiver uma solicitação de longo prazo, escreva uma carta e pronto. Ou seja, você não precisa olhar com os olhos, pode ser automatizado. Você receberá uma carta e reagirá a ela. Ou você pode atirar automaticamente.

Existem razões óbvias para isso acontecer?

Eu listei alguns. Outros exemplos mais complexos. E pode haver uma conversa por muito tempo.

Obrigado pelo relatório! Queria esclarecer sobre o utilitário pg_repack. Se ela não fizer um bloqueio exclusivo, então...

Ela faz uma fechadura exclusiva.

... então eu poderia potencialmente perder dados. Meu aplicativo não deveria gravar nada durante esse período?

Não, funciona perfeitamente com a tabela, ou seja, o pg_repack primeiro transfere todas as linhas ativas que existem. Naturalmente, ocorre algum tipo de entrada na tabela. Ele está apenas jogando esse rabo de cavalo fora.

Ou seja, ele realmente faz isso no final?

No final, ele pega um cadeado exclusivo para trocar esses arquivos.

Será mais rápido que VACUUM FULL?

VACUUM FULL, assim que iniciou, imediatamente tomou trava exclusiva. E até que ele faça tudo, ele não a deixará ir. E o pg_repack possui bloqueio exclusivo apenas no momento da substituição do arquivo. Neste momento você não vai escrever aí, mas os dados não serão perdidos, tudo ficará bem.

Olá! Você falou sobre o funcionamento do aspirador de carro. Havia um gráfico com células de registro vermelhas, amarelas e verdes. Ou seja, os amarelos - ele os marcou como excluídos. E como resultado, algo novo pode ser escrito neles?

Sim. Postgres não exclui linhas. Ele tem essa especificidade. Se atualizarmos uma linha, marcamos a antiga como excluída. O id da transação que alterou esta linha aparece ali e escrevemos uma nova linha. E temos sessões que poderiam potencialmente lê-los. Em algum momento eles ficam bastante velhos. E a essência de como o autovácuo funciona é que ele passa por essas linhas e as marca como desnecessárias. E você pode substituir os dados lá.

Eu entendo. Mas não é disso que se trata. Eu não terminei. Vamos supor que temos uma mesa. Possui campos de tamanho variável. E se eu tentar inserir algo novo, pode simplesmente não caber na célula antiga.

Não, em qualquer caso toda a linha é atualizada lá. Postgres possui dois modelos de armazenamento de dados. Ele seleciona o tipo de dados. Existem dados que são armazenados diretamente na tabela e também existem dados tos. São grandes quantidades de dados: texto, json. Eles são armazenados em pratos separados. E de acordo com esses tablets, ocorre a mesma história com o inchaço, ou seja, tudo é igual. Eles estão listados apenas separadamente.

Obrigado pelo relatório! É aceitável usar consultas de tempo limite de instrução para limitar a duração?

Muito aceitável. Usamos isso em todos os lugares. E como não temos serviços próprios, oferecemos suporte remoto, temos uma variedade de clientes. E todos estão completamente satisfeitos com isso. Ou seja, temos cron jobs que verificam. A duração das sessões é simplesmente acordada com o cliente, antes da qual não concordamos. Pode demorar um minuto, pode demorar 10 minutos. Depende da carga na base e da sua finalidade. Mas todos nós usamos pg_stat_activity.

Obrigado pelo relatório! Estou tentando aplicar seu relatório às minhas aplicações. E parece que iniciamos uma transação em todos os lugares e a concluímos claramente em todos os lugares. Se houver alguma exceção, a reversão ainda ocorrerá. E então comecei a pensar. Afinal, a transação pode não começar explicitamente. Esta é provavelmente uma dica para a garota. Se eu apenas atualizar um registro, a transação começará no PostgreSQL e só será concluída quando a conexão for desconectada?

Se você está falando agora sobre o nível do aplicativo, então depende do driver que você está usando, do ORM que está sendo usado. Existem muitas configurações lá. Se você tiver o commit automático ativado, uma transação começa aí e fecha imediatamente.

Ou seja, fecha imediatamente após a atualização?

Depende das configurações. Eu nomeei uma configuração. Este é o commit automático ativado. É bastante comum. Se estiver ativado, a transação foi aberta e fechada. A menos que você tenha dito explicitamente “iniciar transação” e “finalizar transação”, mas simplesmente lançou uma solicitação na sessão.

Olá! Obrigado pelo relatório! Vamos imaginar que temos um banco de dados que vai aumentando e aumentando e aí o espaço no servidor acaba. Existem ferramentas para corrigir esta situação?

O espaço no servidor precisa ser monitorado adequadamente.

Por exemplo, o DBA foi tomar chá, esteve em um resort, etc.

Quando um sistema de arquivos é criado, pelo menos algum tipo de espaço de backup é criado onde os dados não são gravados.

E se estiver completamente abaixo de zero?

Lá ele é chamado de espaço reservado, ou seja, pode ser liberado e dependendo do tamanho que foi criado, você ganha espaço livre. Por padrão, não sei quantos existem. E em outro caso, entregue os discos para que você tenha espaço para realizar uma operação reconstrutiva. Você pode excluir alguma tabela da qual você certamente não precisará.

Existem outras ferramentas?

É sempre feito à mão. E localmente fica claro o que é melhor fazer ali, porque alguns dados são críticos e outros não. E para cada banco de dados e aplicação que funciona com ele, depende do negócio. É sempre decidido localmente.

Obrigado pelo relatório! Eu tenho duas perguntas. Primeiro, você mostrou slides que mostraram que quando as transações ficam travadas, tanto o tamanho do espaço de tabela quanto o tamanho do índice aumentam. E mais adiante no relatório havia vários utilitários que empacotam o tablet. E o índice?

Eles os embalam também.

Mas o vácuo não afeta o índice?

Alguns trabalham com um índice. Por exemplo, pg_rapack, pgcompacttable. O vácuo recria os índices e os afeta. Com VACUUM FULL a ideia é sobrescrever tudo, ou seja, funciona com todos.

E a segunda pergunta. Não entendo por que os relatórios sobre réplicas dependem tanto da própria replicação. Pareceu-me que os relatórios são lidos e a replicação é escrita.

O que causa um conflito de replicação? Temos um Master no qual ocorrem os processos. Temos um aspirador de carro em funcionamento. O que um aspirador automático realmente faz? Ele está cortando algumas falas antigas. Se neste momento tivermos uma solicitação na réplica que lê essas linhas antigas, e no Master ocorreu uma situação em que o autovacuum marcou essas linhas como possíveis para substituição, então as sobrescrevemos. E recebemos um pacote de dados, quando precisarmos reescrever aquelas linhas que a solicitação necessita na réplica, o processo de replicação irá aguardar o tempo limite que você configurou. E então o PostgreSQL decidirá o que é mais importante para ele. E a replicação é mais importante para ele do que a requisição, e ele vai disparar a requisição para fazer essas alterações na réplica.

Andrey, tenho uma pergunta. Esses gráficos maravilhosos que você mostrou durante a apresentação, são fruto do trabalho de algum tipo de utilidade sua? Como foram feitos os gráficos?

Este é um serviço Okmetro.

Este é um produto comercial?

Sim. Este é um produto comercial.

Fonte: habr.com

Adicionar um comentário