PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como obter o melhor dos logs do PostgreSQL


Como um RDBMS moderno, o PostgreSQL vem com muitos parâmetros para ajuste fino. Uma das áreas a serem consideradas é como o PostgreSQL deve registrar suas atividades. O log é frequentemente negligenciado no gerenciamento de banco de dados Postgres e, se não for ignorado, geralmente configurado incorretamente. Isso acontece porque, na maioria das vezes, o objetivo do registro não é claro. É claro que a razão fundamental para o registro em log é bem conhecida, mas o que às vezes falta é uma compreensão de como os logs serão usados.

Os requisitos de registro de cada organização são exclusivos e, portanto, como o registro do PostgreSQL deve ser configurado também será diferente. O que uma empresa de serviços financeiros precisa capturar em seus logs de banco de dados será diferente do que uma empresa que lida com informações críticas de saúde precisa registrar. E em alguns casos, eles podem ser semelhantes também.

Neste artigo, abordarei algumas práticas fundamentais para obter o melhor dos logs do PostgreSQL. Este blog não é um livro de regras rígido e rápido; os leitores são mais do que bem-vindos para compartilhar seus pensamentos na seção de comentários. No entanto, para obter o melhor valor disso, peço ao leitor que pense em como deseja usar os logs do servidor de banco de dados PostgreSQL:
  • Motivo de conformidade legal em que informações específicas precisam ser capturadas
  • Auditoria de segurança em que detalhes específicos do evento precisam estar presentes
  • Solução de problemas de desempenho onde as consultas e seus parâmetros devem ser registrados
  • Suporte operacional diário em que um determinado número de métricas deve ser monitorado

Dito isso, vamos começar.

Não faça alterações manuais no postgresql.conf


Quaisquer alterações no arquivo postgresql.conf devem ser feitas usando um sistema de gerenciamento de configuração como Puppet, Ansible ou Chef. Isso garante que as alterações sejam rastreáveis ​​e possam ser revertidas com segurança para uma versão anterior, se necessário. Isso é verdade quando você está fazendo alterações nos parâmetros de log.

Os DBAs geralmente criam várias cópias do arquivo postgresql.conf, cada uma com parâmetros ligeiramente diferentes, cada uma para uma finalidade diferente. Gerenciar manualmente diferentes arquivos de configuração é uma tarefa complicada se não for propenso a erros. Por outro lado, um sistema de gerenciamento de configuração pode ser feito para renomear e usar diferentes versões do arquivo postgresql.conf com base em um parâmetro passado para ele. Este parâmetro ditará a finalidade da versão atual. Quando a necessidade for concluída, o arquivo de configuração antigo pode ser recuperado alterando o mesmo parâmetro de entrada.

Por exemplo, se você deseja registrar todas as instruções em execução em sua instância do PostgreSQL, um arquivo de configuração com o valor do parâmetro “log_statement=all” pode ser usado. Quando não há necessidade de gravar todas as instruções – talvez após um exercício de solução de problemas – o arquivo de configuração anterior pode ser restabelecido.

Use arquivos de log separados para PostgreSQL


Eu recomendo habilitar o coletor de log nativo do PostgreSQL durante as operações normais. Para habilitar o log nativo do PostgreSQL, defina o seguinte parâmetro como on:
logging_collector = on

Há duas razões para isso:

Em primeiro lugar, em sistemas ocupados, o sistema operacional pode não registrar consistentemente as mensagens do PostgreSQL no syslog (assumindo uma instalação baseada em nix) e muitas vezes descartar as mensagens. Com o registro nativo do PostgreSQL, um daemon separado cuida da gravação dos eventos. Quando o PostgreSQL estiver ocupado, esse processo adiará a gravação nos arquivos de log para permitir que os encadeamentos de consulta terminem. Isso pode bloquear todo o sistema até que o evento de log seja gravado. Portanto, é útil gravar mensagens menos detalhadas no log (como veremos mais adiante) e usar prefixos de linha de log abreviados.

Em segundo lugar – e como veremos mais adiante – os logs devem ser coletados, analisados, indexados e analisados ​​com um utilitário Log Management. Ter o PostgreSQL gravando seus eventos no syslog significará criar uma camada extra de filtragem e correspondência de padrões na parte de gerenciamento de logs para filtrar todas as “mensagens de ruído”. Arquivos de log dedicados podem ser facilmente analisados ​​e indexados para eventos pela maioria das ferramentas.

Definir destino do log como stderr


Vamos considerar o parâmetro “log_destination”. Pode ter quatro valores:
log_destination = stderr | syslog | csv | eventlog

A menos que haja um bom motivo para salvar eventos de log em formato separado por vírgulas ou log de eventos no Windows, recomendo definir esse parâmetro como stderr. Isso ocorre porque com um destino de arquivo CSV, um valor de parâmetro personalizado “log_line_prefix” não terá nenhum efeito e, ainda assim, o prefixo pode ser feito para conter informações valiosas.

Por outro lado, um log CSV pode ser facilmente importado para uma tabela de banco de dados e posteriormente consultado usando SQL padrão. Alguns usuários do PostgreSQL acham mais conveniente do que manipular arquivos de log brutos. Como veremos mais adiante, as soluções modernas de gerenciamento de logs podem analisar nativamente os logs do PostgreSQL e criar automaticamente insights significativos a partir deles. Com o CSV, o relatório e a visualização devem ser feitos manualmente pelo usuário.

Em última análise, tudo se resume a sua escolha. Se você se sente à vontade para criar seu próprio pipeline de ingestão de dados para carregar os logs CSV em tabelas de banco de dados, limpar e transformar os dados e criar relatórios personalizados que atendam às suas necessidades de negócios, certifique-se de que "log_destination" esteja definido como CSV.

Use nomes de arquivos de log significativos


Quando os arquivos de log do PostgreSQL são salvos localmente, pode não parecer necessário seguir um estilo de nomenclatura. O estilo de nome de arquivo padrão é “postgresql-%Y-%m-%d_%H%M%S.log” para logs não formatados em CSV, o que é suficiente para a maioria dos casos.

A nomenclatura se torna importante quando você salva arquivos de log de vários servidores em um local central, como um servidor de log dedicado, um volume NFS montado ou um bucket do S3. Eu recomendo usar dois parâmetros nesse caso:
log_directory
log_filename

Para armazenar arquivos de log de várias instâncias em um só lugar, primeiro crie uma hierarquia de diretórios separada para cada instância. Isso pode ser algo como o seguinte:
/<Application_Name>/<Environment_Name>/<Instance_Name>

O “log_directory” de cada instância do PostgreSQL pode então ser apontado para sua pasta designada.

Cada instância pode então usar o mesmo valor de parâmetro “log_filename”. O valor padrão criará um arquivo como

postgresql_2020-08-25_2359.log

Para usar um nome mais significativo, defina o “log_filename” para algo assim:
log_filename = "postgresql_%A-%d-%B_%H%M"

Os arquivos de log serão nomeados como:

postgresql_Saturday-23-August_2230

Usar prefixo de linha de registro significativo


Os prefixos de linha de log do PostgreSQL podem conter as informações mais valiosas além da própria mensagem. A documentação do Postgres mostra vários caracteres de escape para a configuração do prefixo do evento de log. Essas sequências de escape são substituídas por vários valores de status em tempo de execução. Alguns aplicativos como o pgBadger esperam um prefixo de linha de log específico.

Eu recomendo incluir as seguintes informações no prefixo:
  • A hora do evento (sem milissegundos):%t
  • Nome do cliente remoto ou endereço IP:%h
  • Nome de usuário:%u
  • Banco de dados acessado:%d
  • Nome do aplicativo:%a
  • ID do processo:%p
  • Encerrando a saída do processo sem sessão:%q
  • O número da linha de registro para cada sessão ou processo, começando em 1:%l

Para entender do que se trata cada campo no prefixo, podemos adicionar uma pequena string literal antes do campo. Portanto, o valor do ID do processo pode ser precedido pelo literal “PID=”, o nome do banco de dados pode ser prefixado com “db=" etc. Aqui está um exemplo:
log_line_prefix = 'time=%t, pid=%p %q db=%d, usr=%u, client=%h , app=%a, line=%l '

Dependendo de onde o evento está vindo, o prefixo da linha de log mostrará valores diferentes. Tanto os processos em segundo plano quanto os processos do usuário registrarão suas mensagens no arquivo de log. Para processos do sistema, especifiquei %q, que suprimirá qualquer texto após o ID do processo (%p). Qualquer outra sessão mostrará o nome do banco de dados, nome do usuário, endereço do cliente, nome do aplicativo e uma linha numerada para cada evento.

Além disso, incluí um único espaço após o prefixo da linha de log. Este espaço separa o prefixo do evento de log da mensagem do evento real. Não precisa ser um caractere de espaço - qualquer coisa como dois-pontos duplos (::), hífen (-) ou outro separador significativo pode ser usado.

Além disso, defina o parâmetro “log_hostname” como 1:
log_hostname = 1

Sem isso, apenas o endereço IP do cliente será mostrado. Em sistemas de produção, normalmente será o endereço do proxy, do balanceador de carga ou do pool de conexões. A menos que você saiba os endereços IP desses sistemas de cor, pode valer a pena registrar seus nomes de host. No entanto, a pesquisa de DNS também adicionará tempo extra para o daemon de log gravar no arquivo.

Outro parâmetro que deve ser definido junto com o “log_line_prefix” é “log_timezone”. Definir isso para o fuso horário local do servidor garantirá que os eventos registrados sejam fáceis de seguir a partir de seu carimbo de data/hora em vez de converter primeiro para a hora local. No snippet de código abaixo, estamos definindo o log_timzeone para o fuso horário padrão do leste da Austrália:
log_timezone = 'Australia/Sydney'

Somente conexões de log


Dois parâmetros controlam como o PostgreSQL registra as conexões e desconexões do cliente. Ambos os parâmetros estão desativados por padrão. Com base nos requisitos de segurança da sua organização, você pode definir um deles como 1 e o outro como 0 (a menos que esteja usando uma ferramenta como pgBadger - mais sobre isso posteriormente).
log_connections = 1
log_disconnections = 0

Definir log_connections como 1 registrará todas as conexões autorizadas, bem como as tentativas conexões. Isso é obviamente bom para auditoria de segurança:um ataque de força bruta pode ser facilmente identificado nos logs. No entanto, com essa configuração habilitada, um ambiente PostgreSQL ocupado com milhares, ou mesmo centenas de conexões válidas de curta duração, poderia ver o arquivo de log sendo inundado.

No entanto, ele também pode identificar problemas de aplicativos que podem não ser óbvios de outra forma. Um grande número de tentativas de conexão de vários endereços de clientes válidos diferentes pode indicar que a instância precisa de um balanceador de carga ou serviço de pool de conexões na frente dela. Um grande número de tentativas de conexão de um único endereço de cliente pode revelar um aplicativo com muitos threads que precisam de algum tipo de limitação.

Registrar somente operações DDL e DML


Há muito debate sobre o que deve ser registrado no log do Postgres – ou seja, qual deve ser o valor do parâmetro “log_statement”. Pode ter três valores:
log_statement = 'off' | 'ddl' | 'mod' | 'all'

Pode ser tentador definir isso como "todos" para capturar todas as instruções SQL em execução no servidor, mas isso nem sempre pode ser uma boa ideia na realidade.

Os sistemas de produção ocupados geralmente executam instruções SELECT, às vezes milhares delas por hora. A instância pode estar funcionando perfeitamente bem, sem problemas de desempenho. Definir esse parâmetro como “all” nesses casos sobrecarregaria desnecessariamente o daemon de log, pois ele precisa gravar todas essas instruções no arquivo.

O que você deseja capturar, no entanto, é qualquer corrupção de dados ou alterações na estrutura do banco de dados que causaram algum tipo de problema. Alterações indesejadas ou não autorizadas no banco de dados causam mais problemas de aplicativo do que a seleção de dados; é por isso que eu recomendo definir este parâmetro para "mod". Com essa configuração, o PostgreSQL registrará todas as alterações de DDL e DML no arquivo de log.

Se sua instância do PostgreSQL estiver moderadamente ocupada (dezenas de consultas por hora), sinta-se à vontade para definir este parâmetro como “all”. Quando estiver solucionando problemas de consultas SELECT de execução lenta ou procurando acesso não autorizado a dados, você também pode definir isso como "todos" temporariamente. Alguns aplicativos como o pgBadger também esperam que você defina isso como “todos”.

Registrar mensagens de "aviso" e up


Se o parâmetro “log_statement” decidir que tipo de instruções serão gravadas, os dois parâmetros a seguir ditam o quão detalhada será a mensagem:
log_min_messages
log_min_error_statement

Cada evento do PostgreSQL tem um nível de mensagem associado. O nível de mensagem pode ser qualquer coisa, desde DEBUG detalhado até PANIC conciso. Quanto menor o nível, mais detalhada é a mensagem. O valor padrão para o parâmetro “log_min_messages” é “WARNING”. Eu recomendo mantê-lo nesse nível, a menos que você queira que as mensagens informativas também sejam registradas.

O parâmetro “log_min_error_statement” controla quais instruções SQL que geram erros serão registradas. Assim como “log_min_message”, qualquer instrução SQL com um nível de gravidade de erro igual ou superior ao valor especificado em “log_min_error_statement” será registrado. O valor padrão é “ERROR”, e recomendo manter o padrão.

Manter os parâmetros de duração do registro como padrão


Então temos os dois parâmetros a seguir:
log_duration
log_min_duration_statement

O parâmetro “log_duration” assume um valor booleano. Quando for definido como 1, a duração de cada instrução concluída será registrada. Se definido como 0, a duração da instrução não será registrada. Esse é o valor padrão e recomendo mantê-lo em 0, a menos que você esteja solucionando problemas de desempenho. Calcular e registrar as durações das instruções faz com que o mecanismo de banco de dados faça um trabalho extra (não importa quão pequeno) e, quando extrapolado para centenas ou milhares de consultas, a economia pode ser significativa.

Por fim, temos o parâmetro “log_min_duration_statement”. Quando este parâmetro é definido (sem unidades, é tomado como milissegundos), a duração de qualquer instrução que seja igual ou maior que o valor do parâmetro será registrada. Definir este valor de parâmetro como 0 registrará a duração de todas as instruções concluídas. Definir isso como -1 desabilitará o log de duração da instrução. Este é o valor padrão, e eu recomendo mantê-lo assim.

A única vez que você deseja definir esse parâmetro como 0 é quando deseja criar uma linha de base de desempenho para consultas executadas com frequência. Tenha em mente, porém, que se o parâmetro “log_statement” estiver definido, as instruções que são registradas não serão repetidas nas mensagens de log mostrando as durações. Portanto, você precisará carregar os arquivos de log em uma tabela de banco de dados e, em seguida, unir os valores de ID de processo e ID de sessão dos prefixos de linha de log para identificar instruções relacionadas e suas durações.

Seja qual for o meio, depois de ter uma linha de base para cada consulta executada com frequência, você pode definir o parâmetro “log_min_duration_statement” para o mais alto dos valores de linha de base. Agora, qualquer consulta executada por mais tempo do que o valor de linha de base mais alto será uma candidata para ajuste fino.

Mantenha a verbosidade da mensagem de erro como padrão


O parâmetro “log_error_verbosity” pode ter três valores possíveis:
log_error_verbosity = terse | standard | verbose

Este parâmetro controla a quantidade de informações que o PostgreSQL irá registrar para cada evento registrado no arquivo de log. A menos que depure um aplicativo de banco de dados, é melhor manter esse parâmetro como “padrão”. O modo detalhado será útil quando você precisar capturar o nome do arquivo ou da função e o número da linha que gerou o erro. Definir isso como “conciso” suprimirá o registro da consulta, o que também pode não ser útil.

Encontre uma política de rotação de registros que funcione para seu Caso de uso


Eu recomendo criar uma política de rotação de log com base no tamanho ou na idade do arquivo de log, mas não em ambos. Dois parâmetros de configuração do PostgreSQL determinam como os logs antigos são arquivados e os novos logs são criados:
log_rotation_age = <number of minutes>
log_rotation_size = <number of kilobytes>

O valor padrão para “log_rotration_age” é 24 horas e o valor padrão para “log_rotation_size” é 10 megabytes.

Na maioria dos casos, ter uma política de rotação de tamanho nem sempre garante que a última mensagem de log no arquivo de log arquivado esteja completamente contida apenas nesse arquivo.

Se o “log_rotation_age” for mantido em seu valor padrão de 24 horas, cada arquivo pode ser facilmente identificado e examinado individualmente, pois cada arquivo conterá um dia de eventos. No entanto, isso também não garante que cada arquivo seja uma unidade independente de logs das últimas 24 horas. Às vezes, uma consulta de desempenho lento pode levar mais de 24 horas para ser concluída; eventos podem estar acontecendo quando o arquivo antigo é fechado e o novo é gerado. Esse pode ser o caso durante um trabalho em lote noturno, resultando em algumas partes das consultas registradas em um arquivo e o restante em outro.

Nossa recomendação é encontrar um período de rotação de registros que funcione para seu caso de uso. Verifique a diferença horária entre dois períodos consecutivos de menor atividade (por exemplo, entre um sábado e outro). Você pode então definir o valor “log_rotation_age” para essa diferença de tempo e, durante um desses períodos, reiniciar o serviço PostgreSQL. Dessa forma, o PostgreSQL irá rodar o arquivo de log atual quando o próximo período de calmaria acontecer. No entanto, se você precisar reiniciar o serviço entre esses períodos, a rotação de log será novamente distorcida. Você terá que repetir esse processo então. Mas como muitas outras coisas no PostgreSQL, tentativa e erro ditarão o melhor valor. Além disso, se você estiver usando um utilitário de gerenciamento de log, a idade ou o tamanho da rotação do log não importará porque o agente do gerenciador de log ingerirá cada evento do arquivo à medida que ele for adicionado.

Use ferramentas como pgBadger


O pgBadger é um poderoso analisador de log do PostgreSQL que pode criar insights muito úteis a partir dos arquivos de log do Postgres. É uma ferramenta de código aberto escrita em Perl com uma pegada muito pequena na máquina em que é executada. A ferramenta é executada a partir da linha de comando e vem com um grande número de opções. Levará um ou mais logs como entrada e pode produzir um relatório HTML com estatísticas detalhadas sobre:
  • Consultas em espera mais frequentes.
  • Consultas que geram a maioria dos arquivos temporários ou os maiores arquivos temporários
  • Consultas de execução mais lenta
  • Duração média da consulta
  • Consultas executadas com mais frequência
  • Erros mais frequentes nas consultas
  • Usuários e aplicativos que executam consultas
  • Estatísticas de pontos de verificação.
  • Autovacuum e autoanalyze estatísticas.
  • Estatísticas de bloqueio
  • Eventos de erro (pânico, fatal, erro e aviso).
  • Perfis de conexão e sessão (por banco de dados, usuário, aplicativo)
  • Perfis de sessão
  • Perfis de consulta (tipos de consulta, consultas por banco de dados/aplicativo)
  • Estatísticas de E/S
  • etc.

Como mencionei antes, alguns dos parâmetros de configuração relacionados ao log precisam ser habilitados para capturar todos os eventos de log para que o pgBadger possa analisar esses logs com eficiência. Como isso pode produzir grandes arquivos de log com muitos eventos, o pgBadger deve ser usado apenas para criar benchmarks ou solucionar problemas de desempenho. Uma vez que os logs detalhados tenham sido gerados, os parâmetros de configuração podem ser alterados de volta para seus valores originais. Para análise de log contínua, é melhor usar um aplicativo de gerenciamento de log dedicado.

Se você se sentir mais confortável fazendo coisas no prompt de comando e usando as visualizações do sistema, convém usar pg_stat_statements. Na verdade, isso deve ser ativado em qualquer instalação de produção do PostgreSQL.

pg_stat_statements é uma extensão do PostgreSQL e com a instalação padrão agora. Para habilitá-lo, o parâmetro de configuração “shared_preload_libraries” deve ter pg_stat_statements como um de seus valores. Ele pode ser instalado como qualquer outra extensão usando o comando “CREATE EXTENSION”. A extensão cria a visualização pg_stat_statement que fornece informações valiosas relacionadas à consulta.

Use um aplicativo de gerenciamento de logs para obter insights


Existem muitos utilitários de gerenciamento de log no mercado, e a maioria das organizações usa um ou mais atualmente. Qualquer que seja a ferramenta, recomendo usá-la para coletar e gerenciar os logs do PostgreSQL.

Existem algumas razões para isso:

É muito mais fácil analisar, analisar e filtrar ruídos de arquivos de log com uma ferramenta automatizada. Às vezes, um evento pode abranger vários arquivos de log com base na duração do evento e na idade ou tamanho da rotação do log. Ter um gerenciador de logs torna muito mais simples ter essas informações apresentadas como um todo.

As soluções de gerenciamento de log atuais normalmente vêm com a capacidade integrada de analisar os logs do PostgreSQL. Alguns também vêm com painéis que podem mostrar as métricas mais comuns extraídas desses logs.

A maioria dos aplicativos modernos de gerenciamento de log também oferece recursos avançados de pesquisa, filtro, correspondência de padrões, correlação de eventos e análise de tendências habilitadas para IA. O que não é visível aos olhos comuns pode ser facilmente evidenciado por essas ferramentas.

Por fim, usar um gerenciador de logs para armazenar os logs do PostgreSQL também significa que os eventos serão salvos para a posteridade, mesmo que os arquivos originais sejam excluídos acidentalmente ou maliciosamente.

Embora existam vantagens óbvias de usar um aplicativo de gerenciamento de log, muitas organizações têm restrições sobre onde seus logs podem viver. Esse é um caso típico de soluções baseadas em SaaS, em que os logs geralmente são salvos fora do limite geográfico de uma organização – algo que pode não estar em conformidade com os requisitos regulatórios.

Nesses casos, recomendo escolher um fornecedor com presença de data center local – se possível – ou usar um gerenciador de log autogerenciado hospedado na rede da organização, como uma pilha ELK.

Palavras Finais


Os logs do servidor PostgreSQL podem ser uma mina de ouro de informações quando configurados adequadamente. O truque é determinar o que registrar e quanto registrar e, mais importante, testar se os registros podem fornecer as informações corretas quando necessário. Será uma questão de tentativa e erro, mas o que discuti aqui hoje deve dar um começo bastante decente. Como eu disse no início, ficaria mais do que feliz em ouvir sobre sua experiência de configuração de log do PostgreSQL para obter resultados ideais.