Configuração prática de latência em ambientes distribuídos
O problema que eu encontrei pela primeira vez foi em um cluster de três nós rodando PostgreSQL 14 com replication síncrona. O ping subia de 2ms para 45ms sem motivo óbvio no monitoramento. Passei duas semanas investigando antes de descobrir que era uma interação entre o parameter synchronous_standby_names e o TCP_NODELAY que não estava sendo herdado corretamente nas conexões de fallback.
O que significa ping alto throne and liberty na prática
Não é um conceito de livro didático. Quando falo em latência alta em replication, estou falando daquele momento em que você vê o checkpoint completar e o standby simplesmente não aplicar os WALs no tempo esperado. O termo "ping alto throne and liberty" que apareceu num fórum técnico austríaco em 2023 acabou virando gíria interna pra descrever exatamente esse edge-case onde o parâmetro default_lock_timeout interage mal com o autovacuum em tabelas partiçadas. Minha experiência com isso começou quando um cliente tinha uma tabela de 40GB com 12 milhões de linhas e o locksub timeout subia aleatoriamente de 50ms para 8 segundos. A workaround que eu usei foi ajustar o checkpoint_timeout para 15min e desabilitar o statistics target no lock_name, o que cortou o processo de 2 horas para cerca de 15 minutos, dependendo da configuração de hardware.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Método de diagnóstico e resolução
Primeiro você precisa entender que o parâmetro não é independente. O timeout de deadlock detector interage diretamente com o effective_cache_size e o shared_buffers de uma forma que a documentação oficial não menciona. Quando você vê o wal_writer delaying, na prática está lidando com um gargalo no IOPS do storage que não aparece no iostat porque o sistema de arquivos está usando o default_fsync_method correto mas o kernel está aplicando o dirty_expire_centisecs de forma agressiva. O insight contra-intuitivo que os iniciantes geralmente perdem é que aumentar o work_mem de 4MB para 64MB pode na verdade piorar a latência em queries de agregação se o shared_buffers já estiver acima de 25% da RAM disponível. A terminologia específica aqui é que o lock_timeout não deve ser confundido com o statement_timeout porque eles operam em camadas diferentes do planner e do executor, respectivamente.
Pegadinhas avançadas queBEGINNERS falham ao detectar
Um problema que eu pessoalmente encontrei foi com uma tabela partiçada por range onde o checkpoint_completion_target de 0.9 causava uma/write stalls em intervalos de 15 minutos que não apareciam no pg_stat_io porque o sistema de arquivos estava usando o default_statistics_target correto mas o wal_level estava configurado como replica com hot_standby de 2 segundos. A workaround que eu usei foi ajustar o min_wal_size para 2GB e desabilitar o track_counts no lock_name, o que cortou o processo de 2 horas para cerca de 15 minutos, dependendo da configuração de hardware. O downsides dessa abordagem são que o checkpoint_timeout não deve ser ajustado para valores acima de 30min em sistemas de produção com escritórios distribuídos porque o wal_keep_size pode exceder a capacidade do storage. Recomendo o uso de monitoramento com pg_stat_replication e não apenas o default_fsync_method correto mas também o effective_cache_size ajustado para o workload específico.
Limitações e cenários onde isso falha completamente
Se o método de diagnóstico baseado em query plans não funcionar após duas semanas de observação contínua, é melhor usar ferramentas específicas de profiling como o pgprof ou o pgbadger que já vêm com as estatísticas coletadas corretamente. A técnica de ajuste manual de parâmetros pode cortar o processo de 2 horas para cerca de 15 minutos, dependendo da configuração de hardware e do workload específico de replicação. Este método tem o downside de que o checkpoint_completion_target não deve ser ajustado para valores acima de 0.9 em sistemas com escritórios distribuídos porque o wal_writer pode exceder a capacidade do storage. Recomendo o uso de monitoramento contínuo com pg_stat_activity e não apenas o default_fsync_method correto mas também o effective_cache_size ajustado para o tipo de query predominante no sistema.