postgresql postgres linux conf tuning

Configurações em Linux

Memória

Memory overcommit

Quando um programa precisa de memória, ele faz uma requisição ao sistema (syscall) pedindo a alocação daquela memória. O sistema deve reservar memória do pool de páginas livres e retornar um endereço para a aplicação ou, caso não haja memória livre suficiente, um código de erro indicando isso. O PostgreSQL consegue lidar bem com o código de erro de alocação de memória, já que nesse caso ele pode liberar memória local ou usar algoritmos diferentes ou tentar novamente em outro momento ou mesmo retornar uma mensagem de erro para a aplicação, que se encarrega de refazer a transação posteriormente. Contudo, quando o endereço é retornado com sucesso, o PostgreSQL depende que a memória para a qual ele aponta esteja realmente disponível.

Nesse ponto, o Linux traz um agravante, já que ele pode retornar a alocação com um sucesso e um endereço válido, mas sem memória física correspondente, deixando a alocação de memória para o momento da primeira escrita de cada página. Isso também significa que mais memória pode ter sido prometida aos programas do que realmente existe no sistema (chamado memory overcommit). E à medida que os processos efetivamente consomem a memória prometida, o sistema pode gerar erros inesperados para os programas quando não houver mais memória livre. Sem memória livre, os programas que precisam de mais memória para continuar não podem finalizar o seu trabalho e, portanto, liberar suas próprias memórias para outros usarem. Essa é uma situação conhecida como deadlock e enunciada como o jantar dos filósofos.

Nesse momento, o sistema se vê obrigado a matar um ou mais processos para que a memória deles possa ser entregue para outros darem continuidade aos seus trabalhos. Isso é chamado de OOM killer (Out-of-memory killer, ou assassino por falta de memória), e pode causar problemas para o seu negócio em função das transações em andamento que são interrompidas sem aviso.

Portanto, é recomendado desabilitar o overcommit_memory, como demonstrado na documentação:

[root@pg-1 ~]# sysctl -w vm.overcommit_memory=2

Ou editando o arquivo /etc/sysctl.conf.

Huge pages

Sistemas operacionais atuais não entregam memória RAM (memória física) diretamente para os processos. Em seu lugar, entregam memória virtual, que é uma estratégia com vantagens em gestão de memória em sistemas multiprocessados, permite alocação de segmentos não contínuos, reuso de endereçamentos por processos distintos e diversas outras.

Contudo, ela também traz alguns pontos importantes de atenção. A tradução do endereçamento virtual para físico é necessária para toda operação de memória. Ela é feita pela MMU (Memory Management Unit, unidade de gerenciamento de memória), que atualmente reside dentro do próprio processador. A MMU carrega uma tabela de tradução de endereços do programa, chamada TLB (Translation Lookaside Buffer), que contém os endereços de cada página do processo.

E cada página tem um tamanho fixo conhecido, que depende da arquitetura e da versão do kernel, mas o valore mais comum é 4kB (getconf PAGESIZE). Processos maiores têm mais memória; com mais memória, mais páginas são alocadas para ele; com mais páginas, a TLB tem mais registros; com mais registros, traduções se tornam mais onerosas e trocas de contexto (quando processos entram e saem do processador) também demoram mais; e, portanto, o desempenho geral sofre.

A solução proposta é aumentar o tamanho da página, o que evita toda a cadeia de consequências. Mas não seria sensato aumentar todas as páginas, já que isso causaria um desperdício de memória em processos pequenos e também traria o risco de falhas nos programas (porque alguns ainda não foram adaptados para trabalhar com tamanhos de página diferentes). Portanto, existe um segundo tipo de página, chamada Huge Page, com um tamanho maior e que é usada apenas pelos programas que decididamente estão prontos para usá-la.

Quando Huge Pages estão disponíveis no sistema, o PostgreSQL as usa. Elas trazem benefícios no PostgreSQL porque a região shared_buffers é compartilhada entre todos os processos dele, portanto diminuir o número de páginas dessa região é diminuir o espaço ocupado pela TLB de todos os processos do PostgreSQL.

Portanto, é possível reservar Huge Pages no sistema operacional, como explicado na documentação:

Descubra o tamanho das páginas:

[root@pg-1 ~]# grep Hugepagesize /proc/meminfo
Hugepagesize:       2048 kB

Ou seja, 2MB. Compare com o valor de shared_buffers:

[postgres@pg-1 ~]$ show shared_buffers;
╔════════════════╗
║ shared_buffers ║
╠════════════════╣
║ 128MB          ║
╚════════════════╝

Para que o PostgreSQL faça a alocação de 128MB em páginas de 2MB, serão necessárias 64 páginas (128MB/2MB = 64).

Altere o número de páginas pré-alocadas para Huge Pages com:

[root@pg-1 ~]# sysctl -w vm.nr_hugepages=64

E reinicie o PostgreSQL, conferindo os contadores de memória:

[root@pg-1 ~]# grep '^HugePages' /proc/meminfo
HugePages_Total:      64
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0

Ou seja, das 64 páginas totais de Huge Pages, 0 estão livres (então todas estão ocupadas).

Obs.: Pode ser necessário ajustar também o grupo que tem permissão de alocar aquelas páginas em memória compartilhada com vm.hugetlb_shm_group, assim como salvar essas configurações em /etc/sysctl.conf.

Sistemas de arquivos

Todo sistema de arquivos que atende a semântica definida pelo padrão POSIX pode ser usado para apoiar o PostgreSQL. Com tudo mais igual, sistemas de arquivos diferentes normalmente não causam diferenças de desempenho do PostgreSQL: documentação.

Pontos de montagem

É comum separarmos os dados do PostgreSQL em volumes (e, portanto, sistemas de arquivos) distintos:

Write barriers

Barreiras de escrita (write barriers) são necessárias para garantir a consistência dos sistemas de arquivos e dos dados de aplicação sobre eles, especialmente quando os os sistemas de arquivos estão sobre controladoras e storages com cache próprio e de baixa confiança. Contudo, quando controladoras e storages têm cache apoiado por baterias e supercapacitores, é seguro desabilitar as barreiras de escrita com uma opção nobarrier no ponto de montagem.

Semáforos e memória compartilhada

O PostgreSQL tem alguns requisitos mínimos sobre semáforos, memória compartilhada e outras primitivas de sincronização interprocessos. Contudo, todas as distribuições Linux atualmente trazem configurações padrão adequadas para ele, então raramente é necessário alterá-las. Para conhecimento, a documentação oficial entra em mais detalhes.