Maintenance

Health check do PostgreSQL no Ubuntu: um script somente leitura que acha os problemas de sempre

PG Monitoring Team August 05, 2026 15 min de leitura

A maioria dos problemas de PostgreSQL não é exótica. É um shared_buffers que ninguém tirou dos 128MB padrão, um replication slot abandonado enchendo o disco em silêncio, uma foreign key sem índice transformando deletes em varredura de tabela inteira e um archive_mode desligado desde a instalação. Este script encontra tudo isso em cerca de um minuto, sem alterar nada.

Um agrado da nossa equipe: o script está abaixo, pronto para copiar ou baixar diretamente. Ele é somente leitura — executa apenas SELECT e SHOW, nunca grava, nunca muda um parâmetro e nunca envia nada para lugar nenhum.

Por que somente leitura importa

Existe muito "script de tuning" que aplica mudanças por você. Não rode esses em um banco que importa: um parâmetro que ajuda uma carga prejudica outra, e um ALTER SYSTEM executado por um script que você leu na diagonal é como uma segunda-feira é arruinada.

Este só lê. Cada achado vem com o comando que resolveria, e você decide se ele se aplica. Concretamente, o script:

  • executa apenas SELECT e SHOW em catálogos e views de estatística;
  • não abre conexão de rede — nada é transmitido, em hipótese alguma;
  • não grava arquivo, a menos que você peça explicitamente um relatório;
  • sai com código diferente de zero quando encontra algo crítico, então funciona em cron ou em uma verificação de CI.

As consultas mais pesadas são varreduras de catálogo limitadas. Em um cluster grande, as verificações de índices e de foreign keys são as mais lentas, e mesmo essas são baratas perto de uma única consulta da aplicação.

O que ele verifica

27 verificações em dez grupos. Os limites são os que usamos em monitoramento de produção, não números redondos arbitrários.

GrupoVerifica
Versão e uptimeVersões major sem suporte; restart recente demais para as estatísticas valerem algo
Memóriashared_buffers versus RAM, pior caso de work_mem, effective_cache_size
Planner e storagerandom_page_cost em SSD, checkpoints forçados por volume de WAL
ConexõesUso versus limite, idle in transaction, consultas acima de 60s, espera por lock
CacheCache hit ratio, arquivos temporários indo para disco
AutovacuumAutovacuum desligado, tabelas com bloat, estatísticas ausentes, wraparound de transaction ID
ÍndicesÍndices grandes sem uso, foreign keys sem índice, duplicados
ReplicaçãoLag da réplica, replication slots abandonados
Backup e WALarchive_mode, falhas de arquivamento, crescimento do pg_wal, data checksums
SegurançaAutenticação trust, senhas md5, quantidade de superusers, SSL, log de consultas lentas

Os achados que mais importam

Quatro deles merecem explicação, porque são os que causam incidentes de verdade e os que mais surpreendem quem roda o script.

Wraparound de transaction ID

Os IDs de transação do PostgreSQL são de 32 bits e dão a volta. Para proteger seus dados, o servidor recusa toda escrita quando o limite se aproxima — uma parada total que chega sem aviso se ninguém estava olhando. O script informa a idade da transação não congelada mais antiga e alerta bem antes desse ponto. A causa raiz normalmente não é autovacuum lento, e sim algo o bloqueando: uma transação aberta há dias, um replication slot abandonado ou uma prepared transaction esquecida.

Replication slots abandonados

Um replication slot manda o servidor reter WAL até o consumidor ler. Se esse consumidor some — uma réplica desativada, um subscriber lógico que alguém apagou, um backup que travou —, o slot fica, e o servidor retém WAL para sempre. Acumula até o pg_wal encher o filesystem e o banco parar. Essa é uma das formas mais comuns de um PostgreSQL saudável cair, e é inteiramente evitável.

Foreign keys sem índice

O PostgreSQL indexa automaticamente o lado pai de uma foreign key, mas não o lado filho. Então todo DELETE ou UPDATE de chave no pai varre a tabela referenciadora inteira para validar a constraint. É invisível enquanto as tabelas são pequenas e brutal quando deixam de ser. Já vimos um único índice faltando levar um delete de 47 segundos para menos de um milissegundo.

Índices sem uso precisam de um ciclo completo de negócio antes do julgamento. idx_scan = 0 significa "não usado desde a última vez que as estatísticas foram zeradas" — que pode ser desde o último restart. Um índice que só serve ao fechamento mensal parece inútil por 29 dias. Confira o pg_stat_reset_time e valide ao longo de um ciclo inteiro antes de derrubar qualquer coisa.

O shared_buffers de 128MB

O padrão serve para um notebook, não para um servidor. Em uma máquina com 32 GB de RAM, significa que o banco praticamente não guarda nada no próprio cache e relê do sistema operacional o tempo todo. O script calcula o valor como percentual da RAM física e sugere cerca de 25%, que é o ponto de partida aceito para a maioria das cargas.

Requisitos

Execute como o usuário de sistema postgres, que autentica localmente por peer e dispensa senha:

sudo apt update
sudo apt install -y postgresql-client

sudo install -m 750 -o postgres -g postgres   postgresql-health-check-ubuntu.sh /usr/local/bin/

sudo -u postgres /usr/local/bin/postgresql-health-check-ubuntu.sh

Algumas verificações — hashes de senha em pg_authid, pg_hba_file_rules — exigem superuser ou a role pg_read_all_settings. Sem isso o script degrada com elegância: essas verificações ficam silenciosas em vez de derrubar a execução. As verificações de memória leem /proc/meminfo, então só reportam no Linux.

# Inspecionar um banco específico nas verificações de tabelas e índices
sudo -u postgres DATABASE=app /usr/local/bin/postgresql-health-check-ubuntu.sh

# Servidor remoto (a role precisa de pg_monitor para cobertura completa)
sudo -u postgres PGHOST=db.interno PGUSER=monitor   /usr/local/bin/postgresql-health-check-ubuntu.sh

Lendo a saída

Cada achado é [CRITICAL], [WARNING] ou [OK], seguido do porquê importa e do comando que resolve:

── Backup and WAL
  [CRITICAL] WAL archiving is disabled (archive_mode = off)
              Point-in-time recovery is impossible. Recovery is limited
              to whatever your last dump captured.
              fix: Enable archive_mode and archive_command

  [   OK   ] pg_wal size: 224 MB (14 segments)

── Security
  [CRITICAL] 4 pg_hba.conf rules use 'trust' for non-local connections
              Anyone who can reach the port connects as any user, with no password.
              fix: Replace trust with scram-sha-256 in pg_hba.conf and reload.

══ Summary ══

  Critical : 2    need attention now
  Warnings : 8    should be planned
  Passed   : 17   of 27 checks

Como ele sai com código diferente de zero quando existe achado crítico, também funciona sem supervisão:

# Verificação semanal, com e-mail apenas quando houver algo crítico
0 8 * * 1 /usr/local/bin/postgresql-health-check-ubuntu.sh > /tmp/hc.txt 2>&1   || mail -s "Health check do PostgreSQL: achados críticos" dba@exemplo.com < /tmp/hc.txt

O script completo

Salve como postgresql-health-check-ubuntu.sh ou baixe o arquivo pronto. Ele é longo porque cada verificação carrega a própria explicação e correção — e é justamente esse o ponto.

#!/usr/bin/env bash
#
# Health check somente leitura de um ambiente PostgreSQL no Ubuntu.
#
# Uso:
#   sudo -u postgres ./postgresql-health-check-ubuntu.sh
#   sudo -u postgres DATABASE=app ./postgresql-health-check-ubuntu.sh
#   sudo -u postgres FULL_REPORT=1 ./postgresql-health-check-ubuntu.sh
#
set -Eeuo pipefail

CONTACT_NAME="${CONTACT_NAME:-João Victor Oliveira — PG Monitoring}"
CONTACT_WHATSAPP="${CONTACT_WHATSAPP:-+55 62 98156-1666}"
CONTACT_EMAIL="${CONTACT_EMAIL:-joao.victor.32@hotmail.com}"
CONTACT_SITE="${CONTACT_SITE:-https://pgmonitoring.com}"

DATABASE="${DATABASE:-}"
FULL_REPORT="${FULL_REPORT:-0}"

CRITICAL_COUNT=0
WARNING_COUNT=0
OK_COUNT=0
FINDINGS_FILE="$(mktemp)"
trap 'rm -f "$FINDINGS_FILE"' EXIT

if [[ -t 1 ]]; then
  BOLD=$'\033[1m'; RED=$'\033[31m'; YELLOW=$'\033[33m'
  GREEN=$'\033[32m'; CYAN=$'\033[36m'; RESET=$'\033[0m'
else
  BOLD=''; RED=''; YELLOW=''; GREEN=''; CYAN=''; RESET=''
fi

fail() { echo "ERRO: $*" >&2; exit 1; }
section() { printf '\n%s── %s %s\n' "$BOLD$CYAN" "$1" "$RESET"; }

# report <CRITICAL|WARNING|OK> <titulo> <detalhe> [correcao]
report() {
  local level="$1" title="$2" detail="$3" fix="${4:-}"
  case "$level" in
    CRITICAL) CRITICAL_COUNT=$((CRITICAL_COUNT + 1))
              printf '  %s[CRITICAL]%s %s\n' "$RED$BOLD" "$RESET" "$title" ;;
    WARNING)  WARNING_COUNT=$((WARNING_COUNT + 1))
              printf '  %s[WARNING ]%s %s\n' "$YELLOW" "$RESET" "$title" ;;
    OK)       OK_COUNT=$((OK_COUNT + 1))
              printf '  %s[   OK   ]%s %s\n' "$GREEN" "$RESET" "$title" ;;
  esac
  [[ -n "$detail" ]] && printf '              %s\n' "$detail"
  [[ -n "$fix" ]] && printf '              %sfix:%s %s\n' "$BOLD" "$RESET" "$fix"
  printf '%s\t%s\t%s\t%s\n' "$level" "$title" "$detail" "$fix" >> "$FINDINGS_FILE"
}

q()  { psql -XAtq --no-password -d "${PGDATABASE:-postgres}" -c "$1" 2>/dev/null || echo ""; }
qd() { psql -XAtq --no-password -d "$DATABASE" -c "$1" 2>/dev/null || echo ""; }

# Comparações que toleram resultado vazio de uma consulta que falhou.
gt() { [[ -n "$1" ]] && awk -v a="$1" -v b="$2" 'BEGIN { exit !(a > b) }'; }
lt() { [[ -n "$1" ]] && awk -v a="$1" -v b="$2" 'BEGIN { exit !(a < b) }'; }

command -v psql >/dev/null || fail "psql não encontrado. Instale o postgresql-client."

SERVER_VERSION="$(q 'SHOW server_version')"
[[ -n "$SERVER_VERSION" ]] || fail "Não foi possível conectar. Execute como: sudo -u postgres $0"
SERVER_VERSION_NUM="$(q 'SHOW server_version_num')"
[[ -z "$DATABASE" ]] && DATABASE="$(q 'SELECT current_database()')"

printf '\n  PostgreSQL Environment Health Check\n  %s\n\n' "$CONTACT_SITE"
printf '  Servidor  : PostgreSQL %s\n' "$SERVER_VERSION"
printf '  Host      : %s\n' "$(hostname -f 2>/dev/null || hostname)"
printf '  Banco     : %s\n' "$DATABASE"
printf '  Modo      : somente leitura (nada é alterado)\n'

# ── Versão ─────────────────────────────────────────────────────────────
section "Versão e uptime"

if lt "$SERVER_VERSION_NUM" 130000; then
  report CRITICAL "PostgreSQL $SERVER_VERSION está fora de suporte" \
    "Esta versão não recebe mais correções de segurança nem de bugs." \
    "Planeje upgrade de major com pg_upgrade; teste antes em uma cópia restaurada."
elif lt "$SERVER_VERSION_NUM" 150000; then
  report WARNING "PostgreSQL $SERVER_VERSION tem suporte, mas está defasado" \
    "Versões mais novas trazem ganhos importantes de desempenho e observabilidade." \
    "Avalie um caminho de upgrade na próxima janela de manutenção."
else
  report OK "PostgreSQL $SERVER_VERSION é uma major com suporte atual" "" ""
fi

# ── Memória ────────────────────────────────────────────────────────────
section "Configuração de memória"

TOTAL_RAM_MB="$(awk '/MemTotal/ { printf "%d", $2 / 1024 }' /proc/meminfo 2>/dev/null || echo "")"
SHARED_BUFFERS_MB="$(q "SELECT (setting::bigint * current_setting('block_size')::bigint / 1024 / 1024) FROM pg_settings WHERE name = 'shared_buffers'")"

if [[ -n "$TOTAL_RAM_MB" && -n "$SHARED_BUFFERS_MB" ]]; then
  SB_PCT="$(awk -v s="$SHARED_BUFFERS_MB" -v t="$TOTAL_RAM_MB" 'BEGIN { printf "%.1f", (s / t) * 100 }')"
  TARGET_MB=$(( TOTAL_RAM_MB / 4 ))
  if lt "$SB_PCT" 10; then
    report CRITICAL "shared_buffers tem apenas ${SB_PCT}% da RAM (${SHARED_BUFFERS_MB} MB de ${TOTAL_RAM_MB} MB)" \
      "O padrão de 128MB é sobra comum de instalação; força releitura constante do disco." \
      "ALTER SYSTEM SET shared_buffers = '${TARGET_MB}MB';  -- depois reinicie"
  elif gt "$SB_PCT" 40; then
    report WARNING "shared_buffers está em ${SB_PCT}% da RAM (${SHARED_BUFFERS_MB} MB)" \
      "Acima de ~40% o cache do sistema operacional fica sem espaço e o buffer duplo desperdiça memória." \
      "Considere reduzir para perto de 25% da RAM (${TARGET_MB}MB)."
  else
    report OK "shared_buffers: ${SHARED_BUFFERS_MB} MB (${SB_PCT}% da RAM)" "" ""
  fi
fi

WORK_MEM_KB="$(q "SELECT setting::bigint FROM pg_settings WHERE name = 'work_mem'")"
MAX_CONN="$(q "SELECT setting::int FROM pg_settings WHERE name = 'max_connections'")"
if [[ -n "$WORK_MEM_KB" ]]; then
  WORK_MEM_MB=$(( WORK_MEM_KB / 1024 ))
  if lt "$WORK_MEM_KB" 8192; then
    report WARNING "work_mem tem apenas ${WORK_MEM_KB} kB" \
      "Ordenações e hashes que passam disso vão para arquivos temporários em disco." \
      "Aumente aos poucos (ex.: 16MB); ele é alocado por operação, não por conexão."
  else
    WORST_CASE_MB=$(( (WORK_MEM_KB / 1024) * MAX_CONN ))
    if [[ -n "$TOTAL_RAM_MB" ]] && gt "$WORST_CASE_MB" "$TOTAL_RAM_MB"; then
      report WARNING "work_mem (${WORK_MEM_MB} MB) x max_connections (${MAX_CONN}) = ${WORST_CASE_MB} MB, acima da RAM total" \
        "work_mem é por nó de sort/hash, então picos podem esgotar a memória e acionar o OOM killer." \
        "Reduza work_mem, reduza max_connections ou coloque um pooler na frente."
    else
      report OK "work_mem: ${WORK_MEM_MB} MB" "" ""
    fi
  fi
fi

# ── Conexões ───────────────────────────────────────────────────────────
section "Conexões"

IDLE_IN_TX="$(q "SELECT count(*) FROM pg_stat_activity
  WHERE state = 'idle in transaction' AND state_change < now() - interval '5 minutes'")"
if gt "$IDLE_IN_TX" 10; then
  report CRITICAL "${IDLE_IN_TX} conexões idle in transaction há mais de 5 minutos" \
    "Elas seguram locks e impedem o vacuum de limpar linhas mortas, gerando bloat e travando DDL." \
    "Corrija o controle de transação na aplicação; use idle_in_transaction_session_timeout."
elif gt "$IDLE_IN_TX" 3; then
  report WARNING "${IDLE_IN_TX} conexões idle in transaction há mais de 5 minutos" \
    "Elas seguram o horizonte do vacuum e podem travar mudanças de schema." \
    "ALTER SYSTEM SET idle_in_transaction_session_timeout = '10min';"
else
  report OK "Sem sessões idle in transaction relevantes" "" ""
fi

# ── Autovacuum e wraparound ────────────────────────────────────────────
section "Autovacuum e saúde das tabelas"

AUTOVACUUM="$(q "SELECT setting FROM pg_settings WHERE name = 'autovacuum'")"
if [[ "$AUTOVACUUM" != "on" ]]; then
  report CRITICAL "autovacuum está DESLIGADO" \
    "Linhas mortas nunca são recuperadas. Isso termina em bloat e wraparound de transaction ID." \
    "ALTER SYSTEM SET autovacuum = on;  -- depois recarregue. Nunca deixe desligado."
else
  report OK "autovacuum está habilitado" "" ""
fi

MAX_AGE="$(q "SELECT max(age(datfrozenxid)) FROM pg_database")"
if [[ -n "$MAX_AGE" ]]; then
  if gt "$MAX_AGE" 1500000000; then
    report CRITICAL "A idade de transaction ID é ${MAX_AGE}" \
      "Em 2 bilhões o PostgreSQL recusa novas escritas para proteger os dados. É uma parada anunciada." \
      "Faça vacuum nos bancos mais antigos agora: vacuumdb --all --freeze --jobs=4"
  elif gt "$MAX_AGE" 1000000000; then
    report WARNING "A idade de transaction ID é ${MAX_AGE}" \
      "Aproximando do wraparound; o autovacuum não está congelando rápido o bastante." \
      "Investigue bloqueadores: transações longas, slots abandonados, prepared transactions."
  else
    report OK "Idade de transaction ID saudável (${MAX_AGE})" "" ""
  fi
fi

# ── Índices ────────────────────────────────────────────────────────────
section "Índices"

FK_NO_INDEX="$(qd "
  SELECT count(*)
    FROM pg_constraint c
    JOIN pg_class t ON t.oid = c.conrelid
   WHERE c.contype = 'f'
     AND NOT EXISTS (
       SELECT 1 FROM pg_index i
        WHERE i.indrelid = c.conrelid
          AND (i.indkey::smallint[])[0:array_length(c.conkey,1)-1] @> c.conkey
     )")"
if gt "$FK_NO_INDEX" 0; then
  report WARNING "${FK_NO_INDEX} foreign keys sem índice de apoio" \
    "Todo DELETE ou UPDATE no pai varre a tabela filha inteira para validar a constraint." \
    "Crie índice em cada coluna referenciadora; isso costuma levar deletes de 47s para 1ms."
else
  report OK "Todas as foreign keys têm índice de apoio" "" ""
fi

# ── Replication slots ──────────────────────────────────────────────────
section "Replicação"

INACTIVE_SLOTS="$(q "SELECT count(*) FROM pg_replication_slots WHERE NOT active")"
if gt "$INACTIVE_SLOTS" 0; then
  SLOT_NAMES="$(q "SELECT string_agg(slot_name, ', ') FROM pg_replication_slots WHERE NOT active")"
  report CRITICAL "${INACTIVE_SLOTS} replication slots inativos: ${SLOT_NAMES}" \
    "Um slot abandonado retém WAL indefinidamente até o pg_wal encher o disco e o servidor parar." \
    "Se o consumidor realmente sumiu: SELECT pg_drop_replication_slot('<nome>');"
else
  report OK "Nenhum replication slot abandonado" "" ""
fi

# ── Backup ─────────────────────────────────────────────────────────────
section "Backup e WAL"

ARCHIVE_MODE="$(q "SELECT setting FROM pg_settings WHERE name = 'archive_mode'")"
if [[ "$ARCHIVE_MODE" != "on" ]]; then
  report CRITICAL "Arquivamento de WAL desabilitado (archive_mode = ${ARCHIVE_MODE})" \
    "Point-in-time recovery é impossível. A recuperação fica limitada ao último dump." \
    "Habilite archive_mode e archive_command."
else
  FAILED_ARCHIVES="$(q "SELECT failed_count FROM pg_stat_archiver")"
  if gt "$FAILED_ARCHIVES" 0; then
    report CRITICAL "O arquivamento de WAL tem ${FAILED_ARCHIVES} falhas" \
      "O WAL está acumulando e a cadeia de recuperação tem lacunas. Isso quebra o PITR em silêncio." \
      "Verifique o destino do archive_command: permissão, espaço livre e alcance de rede."
  else
    report OK "Arquivamento de WAL habilitado e saudável" "" ""
  fi
fi

# ── Segurança ──────────────────────────────────────────────────────────
section "Segurança"

TRUST_AUTH="$(q "SELECT count(*) FROM pg_hba_file_rules
  WHERE auth_method = 'trust' AND type != 'local'")"
if gt "$TRUST_AUTH" 0; then
  report CRITICAL "${TRUST_AUTH} regras do pg_hba.conf usam 'trust' para conexões não locais" \
    "Qualquer um que alcance a porta conecta como qualquer usuário, sem senha." \
    "Troque trust por scram-sha-256 no pg_hba.conf e recarregue."
else
  report OK "Sem autenticação 'trust' para conexões remotas" "" ""
fi

# ── Resumo ─────────────────────────────────────────────────────────────
TOTAL=$(( CRITICAL_COUNT + WARNING_COUNT + OK_COUNT ))
printf '\n%s══ Resumo ══%s\n\n' "$BOLD$CYAN" "$RESET"
printf '  %sCríticos : %-3s%s  exigem atenção agora\n' "$RED$BOLD" "$CRITICAL_COUNT" "$RESET"
printf '  %sAvisos   : %-3s%s  devem ser planejados\n' "$YELLOW" "$WARNING_COUNT" "$RESET"
printf '  %sPassaram : %-3s%s  de %s verificações\n' "$GREEN" "$OK_COUNT" "$RESET" "$TOTAL"

# ── Relatório compartilhável opcional ──────────────────────────────────
if [[ "$FULL_REPORT" == "1" ]]; then
  printf '\n  Isto grava os achados e seus dados de contato em um arquivo local.\n'
  printf '  %sNada é transmitido por este script.%s Ctrl-C para pular.\n\n' "$BOLD" "$RESET"

  read -r -p "  Nome        : " LEAD_NAME
  read -r -p "  Empresa     : " LEAD_COMPANY
  read -r -p "  E-mail      : " LEAD_EMAIL
  read -r -p "  Telefone    : " LEAD_PHONE

  REPORT_FILE="pg-health-check-$(date +%Y%m%d%H%M%S).txt"
  {
    echo "PostgreSQL Environment Health Check"
    echo "Gerado em: $(date --iso-8601=seconds)"
    echo
    echo "Nome    : ${LEAD_NAME}"
    echo "Empresa : ${LEAD_COMPANY}"
    echo "E-mail  : ${LEAD_EMAIL}"
    echo "Telefone: ${LEAD_PHONE}"
    echo
    echo "PostgreSQL : ${SERVER_VERSION}"
    echo "Host       : $(hostname -f 2>/dev/null || hostname)"
    echo "Banco      : ${DATABASE}"
    echo
    echo "Resultado: ${CRITICAL_COUNT} críticos, ${WARNING_COUNT} avisos, ${OK_COUNT} aprovados"
    echo
    while IFS=$'\t' read -r level title detail fix; do
      [[ "$level" == "OK" ]] && continue
      echo "[${level}] ${title}"
      [[ -n "$detail" ]] && echo "    ${detail}"
      [[ -n "$fix" ]] && echo "    fix: ${fix}"
      echo
    done < "$FINDINGS_FILE"
  } > "$REPORT_FILE"

  chmod 600 "$REPORT_FILE"
  printf '\n  Relatório gravado em: %s\n' "$REPORT_FILE"
  printf '  Revise e envie para %s ou %s\n' "$CONTACT_WHATSAPP" "$CONTACT_EMAIL"
fi

# ── Contato ────────────────────────────────────────────────────────────
printf '\n%s══ Precisa de ajuda com estes achados? ══%s\n\n' "$BOLD$CYAN" "$RESET"
printf '  %s\n' "$CONTACT_NAME"
printf '  WhatsApp : %s\n' "$CONTACT_WHATSAPP"
printf '  E-mail   : %s\n' "$CONTACT_EMAIL"
printf '  Site     : %s\n\n' "$CONTACT_SITE"

(( CRITICAL_COUNT > 0 )) && exit 1
exit 0

A listagem acima está resumida para caber na leitura — ela mostra a estrutura e as verificações mais valiosas. O arquivo para download traz as 27, incluindo cache hit ratio, arquivos temporários, comportamento de checkpoint, bloat, índices sem uso e duplicados, lag de réplica, crescimento do pg_wal, data checksums, senhas md5, contagem de superusers, SSL e log de consultas lentas.

Quer uma segunda opinião sobre o resultado?

Rodar a verificação é a parte fácil; decidir o que atacar primeiro é onde experiência conta. Execute com FULL_REPORT=1 e o script reúne os achados em um arquivo de texto local, junto dos seus dados de contato, que você pode revisar e nos enviar:

sudo -u postgres FULL_REPORT=1 /usr/local/bin/postgresql-health-check-ubuntu.sh

O arquivo contém apenas o que o relatório imprimiu — achados, versão do PostgreSQL, nome do host, tamanho dos bancos. Sem texto de consulta, sem conteúdo de tabela, sem credenciais. O script nunca transmite esse arquivo; ele grava com chmod 600 e para por aí. Leia, remova o que preferir não compartilhar e envie se quiser a nossa análise.

Respondemos com o que priorizaríamos, o que é seguro mudar imediatamente e o que precisa de janela de manutenção.

Fale direto conosco:
WhatsApp: +55 62 98156-1666
E-mail: joao.victor.32@hotmail.com

Uma foto não é monitoramento

Este script diz o que é verdade agora. A maior parte do que realmente machuca um banco se desenvolve aos poucos: bloat acumulando por semanas, um plano de consulta que degrada conforme a tabela cresce, um vazamento de conexões que só aparece sob carga, lag de replicação que dispara às 3 da manhã e normaliza antes de alguém olhar. Uma verificação que você roda quando já desconfia do problema não pega nada disso.

É isso que o PG Monitoring faz continuamente — as mesmas verificações, acompanhadas ao longo do tempo, com alertas antes de um aviso virar incidente. Use o script para uma resposta pontual; use monitoramento para não ser o último a saber.

Referências: o manual do PostgreSQL documenta as views do coletor de estatísticas, vacuum de rotina e prevenção de wraparound, parâmetros de consumo de recursos e a autenticação via pg_hba.conf.

Related Articles

Ready to experience better PostgreSQL monitoring?

Join thousands of teams who switched from traditional tools to PG Monitoring's AI-powered platform.

Fale conosco