O que acontece no ponto de verificação do PostgreSQL?

22

Aqui está parte do meu log do ponto de verificação:

2014-03-26 11:51:29.341 CDT,,,18682,,532854fc.48fa,4985,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 15047 buffers (1.4%); 0 transaction log file(s) added, 0 removed, 30 recycled; write=68.980 s, sync=1.542 s, total=70.548 s; sync files=925, longest=0.216 s, average=0.001 s",,,,,,,,,""
2014-03-26 11:56:05.430 CDT,,,18682,,532854fc.48fa,4987,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 16774 buffers (1.6%); 0 transaction log file(s) added, 0 removed, 31 recycled; write=72.542 s, sync=17.164 s, total=89.733 s; sync files=885, longest=3.812 s, average=0.019 s",,,,,,,,,""
2014-03-26 12:01:21.650 CDT,,,18682,,532854fc.48fa,4989,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 14436 buffers (1.4%); 0 transaction log file(s) added, 0 removed, 33 recycled; write=122.350 s, sync=5.212 s, total=127.676 s; sync files=924, longest=3.740 s, average=0.005 s",,,,,,,,,""
2014-03-26 12:06:25.028 CDT,,,18682,,532854fc.48fa,4991,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 13277 buffers (1.3%); 0 transaction log file(s) added, 0 removed, 29 recycled; write=126.217 s, sync=5.733 s, total=131.991 s; sync files=894, longest=1.859 s, average=0.006 s",,,,,,,,,""
2014-03-26 12:10:41.958 CDT,,,18682,,532854fc.48fa,4993,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 20765 buffers (2.0%); 0 transaction log file(s) added, 0 removed, 28 recycled; write=88.015 s, sync=10.818 s, total=98.872 s; sync files=881, longest=2.690 s, average=0.012 s",,,,,,,,,""

Percebi que, às vezes, nosso banco de dados é muito lento - é possível ver um número muito grande de consultas normalmente curtas travadas por muito mais tempo do que agora. Isso acontece regularmente sem um culpado claro.

Pergunta: O ponto de verificação pode causar isso? O que acontece na fase de "sincronização" do ponto de verificação?

Konrad Garus
fonte

Respostas:

32

Durante sua operação, o PostgreSQL registra alterações nos arquivos de log de transações, mas não as libera imediatamente nas tabelas reais do banco de dados. Geralmente, apenas mantém as alterações na memória e as retorna da memória quando solicitadas, a menos que a RAM comece a ficar cheia e precise gravá-las.

Isso significa que, se travar, as tabelas em disco não estarão atualizadas. Ele deve reproduzir os logs de transações, aplicando as alterações nas tabelas em disco, antes de poder iniciar o backup. Isso pode demorar um pouco para um banco de dados grande e ocupado.

Por esse motivo, e para que os logs de transações não cresçam para sempre, o PostgreSQL realiza periodicamente um ponto de verificação, onde garante que o banco de dados esteja em um estado limpo. Ele libera todas as alterações pendentes no disco e recicla os logs de transações que estavam sendo usados ​​para manter um registro de recuperação de falhas das alterações.

Esse flush ocorre em duas fases:

  • Tampões write()de sujo shared_bufferspara as mesas; e
  • fsync() dos arquivos afetados para garantir que as alterações realmente atinjam o disco

Ambos podem aumentar a carga de E / S do disco. A contenção causada por essas gravações pode retardar as leituras e também a descarga dos segmentos WAL necessários para confirmar as transações.

Esse é um desafio de longa data, mas está piorando à medida que vemos sistemas com mais e mais RAM, para que eles possam armazenar mais dados em buffer e levar mais tempo para escrevê-los. Há discussões entre as comunidades Linux e PostgreSQL sobre como lidar com isso no momento, conforme discutido neste artigo do LWN.net . (O LWN.net não poderá continuar escrevendo esse tipo de excelente trabalho se as pessoas não se inscreverem. Sou assinante e compartilhando este link porque é útil e informativo. Por favor, considere se inscrever se quiser ver mais tipo de coisa.)

A principal coisa que você pode fazer para reduzir o impacto dos pontos de verificação no momento é espalhar a atividade do ponto de verificação aumentando checkpoint_completion_targetpara que mais dados sejam gravados no momento em que o ponto de verificação final chega. Porém, isso tem um custo - se você atualizar uma página dez vezes (digamos), ela poderá ser gravada em disco várias vezes antes do ponto de verificação com um objetivo de conclusão alto, mesmo que apenas tenha sido estritamente gravada uma vez para segurança contra falhas. Um destino de conclusão mais alto cria padrões de E / S mais suaves, mas sobrecarga geral de E / S.

A outra coisa que você pode fazer para ajudar é dizer ao seu sistema operacional para começar imediatamente a gravar dados quando receber gravações em buffer. É como o lado do kernel da configuração checkpoint_completion_targete tem uma troca semelhante. Consulte a documentação vm linux , em particular dirty_background_bytes, dirty_background_ratio, dirty_expire_centisecs.

Craig Ringer
fonte
A gravação está espalhada por um longo tempo e não acho que esteja causando problemas. E a sincronização, é por acaso um tipo de operação de parar o mundo?
precisa
@KonradGarus A sincronização não deve ser um tipo de operação de parar o mundo, mas geralmente é assim mesmo. Leia o artigo ao qual vinculei acima, é um resumo muito oportuno e útil dos problemas, embora de um ponto de vista bastante técnico. A versão curta é "fsync () no Linux tende a prejudicar completamente o desempenho de qualquer E / S simultânea com o fsync ()". Você pode atenuar isso com as opções de ajuste listadas acima, para reduzir a quantidade que deve ser liberada por um fsync.
Craig Ringer
1

Limpar os buffers sujos do sistema de arquivos do sistema operacional causados ​​por exceder dirty_bytesou dirty_ratio é uma operação de bloqueio em primeiro plano!

Os ajustáveis do kernel dirty_bytes, dirty_background_bytes, dirty_ratio, dirty_background_ratioe dirty_centisecscontrole de descarga de buffers do sistema de arquivos OS sujas no disco. dirty_bytesé o limite em bytes, dirty_ratioé o limite como uma proporção da memória total. dirty_background_bytese dirty_background_ratiosão limites semelhantes, mas a liberação ocorre em segundo plano e não bloqueia outras operações de leitura / gravação até que seja concluída. dirty_centisecsé quantos centisegundos podem passar antes que um flush seja iniciado.

Recentemente, os padrões desses ajustáveis ​​foram reduzidos no Linux, pois o tamanho da memória das máquinas modernas aumentou dramaticamente. Mesmo taxas de 5 e 10% para dirty_background_ratioe dirty_ratioem uma máquina de 256 GB podem inundar um sistema de E / S.

Ajustar dirty_background_bytesou dirty_background_ratioiniciar a limpeza de buffers sujos em segundo plano é complicado. Felizmente, você pode ajustar essas configurações sem precisar parar o PostgreSQL ou o host, repetindo novos valores nos arquivos apropriados:

$ sudo echo [int value of bytes] > /proc/sys/vm/dirty_background_bytes

por exemplo, para definir o número de bytes sujos para acionar uma descarga de fundo. Se você estiver usando uma, apoiada pelo capacitor, ou memória flash cartão de RAID com suporte de bateria (você não quer manter seus dados em caso de um acidente, não é?) Começar por ajuste dirty_background_bytesa 1/2 da gravação de cache tamanho do buffer e dirty_bytespara 3/4 desse tamanho. Monitore seu perfil de E / S com iostats e se você ainda estiver com problemas de latência, isso significa que a carga de gravação do banco de dados ainda está sobrecarregando as liberações do cache do buffer de arquivo. Abaixe os valores até que a latência melhore ou considere atualizar seu subsistema de E / S. Placas FusionIO e SSDs são duas possibilidades para taxa de transferência de E / S extrema.

Boa sorte!

bobl
fonte
O seu comentário sobre dados "sujos" é um ponto relevante para a lentidão. Essencialmente: quanto maior a taxa de sujeira, mais buffer é alocado para dados sujos antes da liberação. Assim, minimizar os atrasos na liberação significa aumentar o buffer sujo ou aumentar o tempo em que os dados sujos podem permanecer na memória.
31816 Peter Teoh