Os pontos de verificação podem ser um grande empecilho nas instalações do PostgreSQL com muitas gravações. O primeiro passo para identificar problemas nessa área é monitorar a frequência com que eles acontecem, o que acaba de ganhar uma interface mais fácil de usar adicionada ao banco de dados recentemente.
Os pontos de verificação são operações de manutenção periódica que o banco de dados executa para garantir que tudo o que está sendo armazenado em cache na memória foi sincronizado com o disco. A ideia é que, depois de terminar um, você possa eliminar a necessidade de se preocupar com entradas mais antigas colocadas no log de gravação antecipada do banco de dados. Isso significa menos tempo para se recuperar após uma falha.
O problema com os pontos de verificação é que eles podem ser muito intensos, porque para concluir um deles é necessário gravar cada bit de dados alterados no cache de buffer do banco de dados no disco. Vários recursos foram adicionados ao PostgreSQL 8.3 que permitem monitorar melhor a sobrecarga do ponto de verificação e reduzi-la espalhando a atividade por um período de tempo mais longo. Eu escrevi um longo artigo sobre essas mudanças chamado Checkpoints e o Background Writer que aborda o que mudou, mas é uma leitura bastante seca.
O que você provavelmente quer saber é como monitorar pontos de verificação em seu sistema de produção e como saber se eles estão acontecendo com muita frequência. Embora as coisas tenham melhorado, "picos de ponto de verificação" onde a E/S do disco se torna muito pesada ainda são possíveis mesmo nas versões atuais do PostgreSQL. E não ajuda que a configuração padrão seja ajustada para espaço em disco muito baixo e recuperação rápida de falhas em vez de desempenho. O parâmetro checkpoint_segments, que é uma entrada sobre a frequência com que um checkpoint acontece, é padronizado para 3, o que força um checkpoint após apenas 48 MB de gravações.
Você pode descobrir a frequência do checkpoint de duas maneiras. Você pode ativar log_checkpoints e observar o que acontece nos logs. Você também pode usar a visualização pg_stat_bgwriter, que fornece uma contagem de cada uma das duas fontes para pontos de verificação (passagem de tempo e ocorrência de gravações), bem como estatísticas sobre quanto trabalho eles fizeram.
O principal problema em tornar isso mais fácil fazer é que, até recentemente, era impossível redefinir os contadores dentro do pg_stat_bgwriter. Isso significa que você precisa tirar um instantâneo com um carimbo de data/hora, esperar um pouco, tirar outro instantâneo e subtrair todos os valores para derivar quaisquer estatísticas úteis dos dados. Isso é uma dor.
Chega de uma dor que eu escrevi um patch para facilitar. Com a versão de desenvolvimento atual do banco de dados, agora você pode chamar pg_stat_reset_shared(‘bgwriter’) e colocar todos esses valores de volta a 0 novamente. Isso permite seguir uma prática que costumava ser comum no PostgreSQL. Antes do 8.3, havia um parâmetro chamado stats_reset_on_server_start que você podia ativar. Isso redefine todas as estatísticas internas do servidor cada vez que você o inicia. Isso significava que você poderia chamar a útil função pg_postmaster_start_time(), comparar com a hora atual e sempre ter uma contagem precisa em termos de operações/segundo de qualquer estatística disponível no sistema.
Ainda não é automático, mas agora que é possível redefinir essas peças compartilhadas, você pode fazer isso sozinho. A primeira chave é integrar a limpeza de estatísticas na sequência de inicialização do servidor. Um script como este funcionará:
pg_ctl start -l $PGLOG -w
psql -c "select pg_stat_reset();"
psql -c "select pg_stat_reset_shared('bgwriter');"
Observe o "-w" no comando start - isso fará com que o pg_ctl espere até que o servidor termine de iniciar antes de retornar, o que é vital se você deseja executar imediatamente uma instrução nele.
Se você já fez isso, e a hora de início do seu servidor é essencialmente a mesma de quando as estatísticas do gravador em segundo plano iniciaram a coleta, agora você pode usar esta consulta divertida:
SELECT
total_checkpoints,
seconds_since_start / total_checkpoints / 60 AS minutes_between_checkpoints
FROM
(SELECT
EXTRACT(EPOCH FROM (now() - pg_postmaster_start_time())) AS seconds_since_start,
(checkpoints_timed+checkpoints_req) AS total_checkpoints
FROM pg_stat_bgwriter
) AS sub;
E obtenha um relatório simples de exatamente com que frequência os pontos de verificação estão acontecendo em seu sistema. A saída fica assim:
total_checkpoints | 9
minutes_between_checkpoints | 3.82999310740741
O que você faz com essa informação é olhar para o intervalo de tempo médio e ver se parece rápido demais. Normalmente, você deseja que um ponto de verificação aconteça a cada cinco minutos, e em um sistema ocupado pode ser necessário empurrá-lo para dez minutos ou mais para ter esperança de acompanhar. Com este exemplo, a cada 3,8 minutos é provavelmente muito rápido – este é um sistema que precisa que checkpoint_segments seja maior.
Usar esta técnica para medir o intervalo de checkpoint permite saber se você precisa aumentar os parâmetros checkpoint_segments e checkpoint_timeout para para atingir esse objetivo. Você pode calcular os números manualmente agora mesmo, e assim que o 9.0 for lançado, é algo que você pode considerar tornar completamente automático – contanto que você não se importe que suas estatísticas desapareçam cada vez que o servidor for reiniciado.
Existem algumas outras maneiras interessantes para analisar os dados que o gravador de segundo plano fornece para você no pg_stat_bgwriter, mas não vou revelar todos os meus truques hoje.