Tuning de SO (no Linux)

Introdução

Tuning refere-se ao processo de ajustar e otimizar o desempenho de um sistema, software ou aplicação. A otimização do sistema operacional é uma etapa crucial para maximizar o desempenho e a eficiência do banco de dados PostgreSQL. Por meio do ajuste de algumas configurações do Linux, é possível melhorar a capacidade de resposta, a estabilidade e a escalabilidade dos serviços. 

Este artigo vai explorar áreas fundamentais para o tuning de sistemas Linux, focando em aspectos-chave como gerenciamento de serviços, sistemas de arquivos, particionamento e parâmetros de configuração do kernel, que impactam diretamente no uso do PostgreSQL.

Roteiro:

  • Systemctl
  • Sistemas de arquivos
  • Particionamento
  • Montagem de discos
  • sysctl.conf 
  • Huge pages
  • Transparent Huge Pages (THP)
  • Limits

Systemctl 

O systemctl é uma ferramenta poderosa para o gerenciamento de serviços no Linux, sendo parte integrante do systemd, o sistema de inicialização e gerenciamento de processos mais utilizado nas distribuições Linux modernas. 

Para DBAs que gerenciam o PostgreSQL, entender como configurar o serviço para iniciar e parar automaticamente durante o boot é essencial para garantir a disponibilidade contínua do banco de dados.

Habilitando a inicialização automática

Para garantir que o serviço do PostgreSQL seja iniciado automaticamente após a reinicialização do sistema, utilizamos o comando systemctl enable. Esse comando cria links simbólicos nos diretórios apropriados, configurando o serviço para ser iniciado durante o processo de boot.

Debian shell: habilitando inicialização automática
sudo systemctl enable postgresql

Se por algum motivo você precisar desativar essa configuração, impedindo que o serviço inicie automaticamente, o comando systemctl disable pode ser utilizado:

Debian shell: desabilitando inicialização automática
sudo systemctl disable postgresql

Iniciando e parando serviços manualmente

Além da configuração automática, também é importante saber como iniciar ou parar manualmente o serviço do PostgreSQL. Para iniciá-lo manualmente, você pode usar o seguinte comando:

Debian shell: iniciando a inicialização aumtomática manualmente
sudo systemctl start postgresql

Já se precisar parar o serviço, o comando é:

Debian shell: parando a inicialização aumtomática manualmente
sudo systemctl stop postgresql

Verificando o status do serviço

Para garantir que o serviço está funcionando corretamente, você pode verificar o status atual do PostgreSQL com o comando abaixo:

ShellSession
sudo systemctl status postgresql

Esse comando retorna informações detalhadas, como se o serviço está ativo, inativo ou se houve falhas recentes, facilitando a administração do sistema.

Sistemas de arquivos

A escolha e a configuração do sistema de arquivos são fundamentais para o desempenho e a confiabilidade de um banco de dados PostgreSQL. Cada sistema de arquivos tem características específicas que podem impactar diretamente na forma como o PostgreSQL gerencia seus dados, especialmente em termos de I/O (entrada/saída) e recuperação em caso de falhas. Confira a seguir alguns dos principais tipos.

EXT4

O EXT4 é o mais recente e mais utilizado sistema de arquivo no Linux, tendo sido criado para superar seu antecessor, o EXT3. Ele é conhecido pela sua robustez e capacidade em termos de confiabilidade e velocidade. Algumas características desse sistema são:

  • Utiliza journaling (mantém um registro das alterações antes de serem aplicadas ao sistema de arquivos, o que ajuda a proteger os dados em caso de falhas de energia ou outras interrupções inesperadas), facilitando a recuperação e minimizando a possibilidade de corrupção de dados;
  • Amplamente compatível com diferentes versões do Linux;
  • Oferece um bom desempenho geral, especialmente para operações de leitura e escrita comuns em ambientes de banco de dados;
  • É escalável, sendo capaz de lidar com volumes de até 1 exabyte e arquivos de até 16 terabytes, atendendo a diversos casos de uso.

XFS

O XFS é um sistema de arquivos mais antigo, porém também de alto desempenho e criado principalmente para lidar com grandes conjuntos de dados, sendo altamente escalável. As características dele são:

  • Como citado, é otimizado para desempenho em sistemas com grandes quantidades de dados;
  • Especialmente eficaz em ambientes em que operações de I/O intensivas são comuns, como em servidores de banco de dados;
  • Também pode suportar sistemas de arquivos de até 16 terabytes;
  • Assim como o EXT4, o XFS também utiliza journaling para proteger a integridade dos dados. No entanto, o XFS possui um sistema de journaling mais sofisticado, que é projetado para minimizar o impacto no desempenho durante a recuperação de falhas.

Outros sistemas de arquivos

Existem inúmeros sistemas de arquivos disponíveis para o Linux, alguns utilizados em situações específicas, nem sempre adequadas para o uso com bancos de dados, por exemplo,  sistemas de arquivos em cluster (como CFS, OCFS, UFS etc.) ou compartilhados (como CFS, OCFS ou GFS2). Outros sistemas são obsoletos, como o EXT2 e o EXT3, que deram lugar ao EXT4. Há também o ReiserFS, que já foi muito utilizado, mas é mais eficiente ao lidar com muitos arquivos pequenos, o que não é performático ao tratar com bancos de dados. Por fim, temos sistemas de arquivos mais modernos, como o BTRFS e o ZFS, que possuem vantagens interessantes, mas nos testes que conhecemos não oferecem uma performance e estabilidade tão boa quanto o EXT4 e o XFS, além de exigirem mais conhecimento para ajustar corretamente.

Na prática, a diferença em termos de performance e segurança é mínima. Um tem pequenas vantagens aqui e ali sobre o outro, mas você pode escolher aquele que se sinta mais confortável de usar. 

O EXT4 é o sistema de arquivos padrão na maioria das distribuições Linux, incluindo o Debian e o Red Hat, mas todos costumam ter suporte para o XFS também.

Particionamento

O particionamento de discos no Linux é uma prática essencial para otimizar o desempenho, a organização e a segurança dos dados em servidores que hospedam bancos de dados. 

Particionar adequadamente o disco pode ajudar a isolar diferentes tipos de dados, melhorar a eficiência de I/O e facilitar a recuperação de dados em caso de falhas.

Existem alguns motivos pelos quais é interessante isolar um servidor de banco de dados em uma partição própria. Alguns deles são:

  • Proteção contra falta de espaço em disco: se o banco de dados ficar na mesma partição do SO, em caso de falta de espaço, você pode ficar sem acesso ao servidor e precisar dar um boot no modo de recuperação, que é um processo bem delicado;
  • Desempenho: ao separar diferentes partes do banco de dados e do SO, você consegue fazer algumas otimizações de desempenho específicas para cada um. Além disso, você pode lidar com diferentes tipos de discos, com maior desempenho ou maior volume, para utilizar em lugares específicos;
  • Proteção contra perda de dados: se você armazenar os dados do servidor em um conjunto de discos, o WAL e seus arquivos de log em outro e tiver um backup físico em outro local, a perda completa dos discos onde os tablespaces estão não resultará em perda de dados. Separar os tablespaces do WAL e seus arquivos de log, além de manter um backup físico em um local separado (outro servidor, disco, fita etc.), é uma política de segurança eficaz para evitar perda de dados.

Quando você utiliza o PostgreSQL num servidor Linux dedicado, você tem diferentes opções de particionamento. Veja aqui algumas opções mais comuns:

  • / (root ou raiz): todo Linux deve ter uma partição dedicada ao SO na raiz. Essa partição em geral não precisa ser muito grande, algo em torno de 20 GB num servidor dedicado costuma ser mais do que o suficiente;
  • /boot: a maioria das distribuições Linux costuma reservar uma pequena partição para o kernel do Linux. Isso já vem por padrão na sua distribuição, você não precisa se preocupar com isso. Apenas não altere nada aí;
  • /data (ou outro nome de diretório a sua escolha): num ambiente de produção, o local de armazenamento do seu banco de dados PostgreSQL (também temos a mania de chamá-lo pelo nome da variável de ambiente $PGDATA) deve ser criado numa partição separada. Essa partição deve ter um tamanho suficientemente grande para acomodar todos os dados pelos próximos anos (pelo menos 3 anos) e ainda ter uma folga de 20% de espaço livre. Nós ensinamos como fazer a instalação num diretório diferente do padrão nos nossos artigos sobre instalação do PostgreSQL no Debian e no Red Hat; 
  • Logs: alguns servidores de produção podem gerar uma quantidade enorme de logs, especialmente se algum erro estranho começar a acontecer de repente ou se você quiser fazer um DEBUG das operações no banco de dados e logar todos os comandos executados nele. Isso pode ocupar um grande espaço em disco e também gerar muito I/O. Separar uma partição só para os logs do PostgreSQL e ajustar o parâmetro log_directory resolve a questão de forma elegante;
  • Backup e archives: você jamais deve guardar os seus backups e archives no mesmo disco físico do seu banco de dados. Na verdade, você não deveria sequer guardar eles no mesmo servidor. O certo seria armazenar esses arquivos num servidor de backup ou num serviço de block storage na nuvem, como a S3;
  • Tablespaces: todo banco de dados relacional armazena os dados em tablespaces. O PostgreSQL já cria por padrão dois tablespaces (o pg_default e o pg_global), que ficam dentro do diretório de dados do PostgreSQL: o $PGDATA. Logo, a maioria das pessoas jamais se preocupa com isso. No entanto, se você tiver discos com capacidades e velocidades distintas, talvez seja melhor separar um tablespace para utilizar apenas uma parte dos dados nesse disco diferente. Já se você tiver discos idênticos, em geral a melhor opção é sempre juntá-los num RAID.

Logical Volume Manager

Muitas pessoas optam no dia a dia pelo uso do LVM2 para juntar diferentes discos em uma única partição e permitir a adição de novos discos no servidor sem ter que desmontar a partição atual. Em troca, você tem uma pequena perda de performance e um aumento na complexidade para gerenciar os discos. Se você tem um profissional competente para lidar com isso, e a flexibilidade é um fator importante para você, usar o LVM2 pode ser uma boa opção. Aqui não vamos demonstrar o seu uso, mas fica a dica como referência.

Montagem de partições

Depois de particionar (utilizando o fdisk ou o cfdisk) e formatar a partição do seu disco (com o mkfs) usando o seu sistema de arquivos predileto (recomendamos anteriormente o EXT4 ou o XFS), chegou a hora de montar as suas partições. Para isso, você deve editar o arquivo /etc/fstab, que contém as configurações de montagem de sistemas de arquivos no Linux. Algumas recomendações são:

  • Utilizar UUIDs (Identificadores Únicos Universais) em vez de nomes de dispositivos: é vantajoso porque UUIDs são imutáveis, mesmo que você adicione ou remova discos no sistema, memória etc., eles não vão mudar de forma inesperada, evitando falhas na montagem de sistemas de arquivos e até na inicialização do servidor;
  • Utilizar a opção noatime para montagem do disco: impede que o sistema atualize a data de acesso aos arquivos toda vez que eles são lidos, reduzindo a carga de I/O no disco e melhorando o desempenho, especialmente em servidores de banco de dados.

Para encontrar os UUIDs das suas partições, você pode consultar o diretório by-uuid:

Debian shell: consultando UUIDs
# ls -lha /dev/disk/by-uuid/
total 0
drwxr-xr-x 2 root root 120 Aug 26 17:06 .
drwxr-xr-x 8 root root 160 Aug 26 16:55 ..
lrwxrwxrwx 1 root root  10 Mar 28 06:01 0bcbad84-23f8-485b-9d66-513bb480a5cb -> ../../vda1
lrwxrwxrwx 1 root root   9 Aug 26 16:50 2024-03-27-15-36-35-00 -> ../../vdb
lrwxrwxrwx 1 root root  11 Mar 28 06:01 DB24-2355 -> ../../vda15
lrwxrwxrwx 1 root root  10 Aug 26 17:06 e59345d7-ea63-4625-98bf-037d425caa50 -> ../../sda1

Aqui, vamos montar a partição sda1. No diretório /data, adicionamos a última linha do nosso arquivo /etc/fstab:

Debian shell: montando a partição
# /etc/fstab: static file system information
UUID=0bcbad84-23f8-485b-9d66-513bb480a5cb / ext4 rw,discard,errors=remount-ro,x-systemd.growfs 0 1
UUID=DB24-2355 /boot/efi vfat defaults 0 0
UUID=e59345d7-ea63-4625-98bf-037d425caa50 /data ext4 noatime 0 0

Nesse exemplo,  a nova partição será montada em /data com o sistema de arquivos ext4, com a opção noatime e “0 0” representando não inclusão no backup automático e não verificação pelo fsck na inicialização.

sysctl.conf

O arquivo sysctl.conf é uma ferramenta essencial para ajustar diversos parâmetros do kernel Linux. Para DBAs que administram servidores PostgreSQL, ajustar as configurações no sysctl.conf pode ajudar a otimizar o desempenho, a eficiência de I/O e a segurança do sistema.

Por ele, podemos mexer em diversas configurações, como:

  • Rede
  • Memória
  • Processos
  • Segurança

Esse arquivo está localizado em /etc/sysctl.conf, e esses parâmetros definem configurações que podem ser aplicadas durante a inicialização do sistema e também em tempo real. Para manipular esses parâmetros, existem duas opções:

  1. Alterar as linhas do arquivo utilizando um editor de texto, como vi ou nano. As alterações feitas diretamente no arquivo são permanentes;
  2. Utilizar os comandos do sysctl. Nesse caso, as alterações são aplicadas apenas para a sessão atual e retornarão ao padrão após o encerramento da sessão.

Além dessas opções, uma abordagem mais moderna e modular é utilizar arquivos de configuração separados no diretório /etc/sysctl.d/. Por exemplo, você pode criar um arquivo chamado /etc/sysctl.d/xx_postgresql.conf para ajustes específicos do PostgreSQL (o xx representa algum número, que servirá para organizar e aplicar as configurações dos arquivos em ordem alfanumérica). Isso permite uma organização mais clara e evita a necessidade de modificar o sysctl.conf principal diretamente.

Configurações gerais que melhoram a performance

  • vm.dirty_ratio = 10: limita a quantidade de memória que o sistema pode usar para guardar dados modificados que ainda não foram salvos no disco. Quando chega a 10%, o sistema começa a gravar esses dados no disco;
  • vm.dirty_background_ratio = 5: quando 5% da memória está cheia de dados não salvos, o sistema começa a gravar esses dados no disco, mas de forma mais tranquila e em segundo plano;
  • vm.overcommit_ratio = 95: informa a partir de qual porção da memória disponível (incluindo a RAM física e o swap em disco) o mecanismo de Out Of Memory Killer (OOM Killer para os íntimos) começará a ser utilizado. O valor padrão é de 50%, que consideramos muito baixo, por isso recomendamos utilizar 95%;
  • vm.overcommit_memory = 2: com essa configuração, o sistema operacional faz algumas checagens adicionais antes de matar um processo por falta de memória usando o OOM Killer. Esse é o nível mais seguro para se utilizar com o PostgreSQL;
  • vm.swappiness = 1: diz ao sistema para usar a memória RAM o máximo possível antes de começar a usar a área de swap (memória em disco), o que ajuda a manter o desempenho rápido.

Para aplicar as mudanças feitas diretamente no arquivo sysctl.conf ou no personalizado dentro do /etc/sysctl.d/, você pode usar o comando sysctl -p. Esse comando recarrega as configurações do sysctl.conf, aplicando as novas definições sem a necessidade de reiniciar o sistema. 

Já para aplicar temporariamente na sessão atual, você pode usar o comando sysctl diretamente, seguido do parâmetro e do valor que deseja configurar. Essas mudanças serão temporárias e durarão até que o sistema seja reiniciado ou a sessão atual seja encerrada.

Exemplo:

Debian shell: ajustando parâmetros de performance
sudo sysctl vm.dirty_ratio=10
sudo sysctl vm.dirty_background_ratio=5
sudo sysctl vm.overcommit_memory=2
sudo sysctl vm.overcommit_ratio=95
sudo sysctl vm.swappiness=1

Huge pages

É um recurso do Linux que permite ao sistema operacional lidar com páginas (blocos) de memória maiores que o padrão de 4 KB. Com páginas maiores, o sistema precisa gerenciar menos páginas, o que reduz o trabalho do processador e melhora o desempenho. Em servidores com 32 GB de RAM ou mais, recomendamos configurar as huge pages.

O PostgreSQL pode ser configurado para utilizar as huge pages, o que é indicado para controle total sobre a alocação de memória e a utilização mais eficiente da RAM. Para configurar o uso das huge pages, basta seguir estes passos:

  • Checar o parâmetro shared_buffers (parâmetro que define a quantidade de RAM para armazenar dados temporários): basta rodar o comando abaixo no psql:
SQL: consultando o parâmetro shared_buffers
SHOW shared_buffers;
  • Calcular o número de huge pages necessárias: precisamos definir o número de páginas, que pode ser calculado com base no valor de shared_buffers + 10%, dividido pelo tamanho da página. Então, o valor das huge pages deve ser = (shared_buffers(em MB) * 1,1)/ 2.

Exemplo: 
shared_buffers = 16 GB
hugepages = (16 * 1024 *1,1) / 2 = 9011

  • Aplicar o valor obtido: para isso, basta editar a linha GRUB_CMDLINE_LINUX no arquivo /etc/default/grub:
Debian shell: aplicando novos valores em parâemtros no arquivo grub
GRUB_CMDLINE_LINUX="... hugepages=9011 hugepagesz=2M transparent_hugepage=never"

É possível também ajustar o valor das huge pages no sysctl, mas em alguns casos (principalmente em servidores com mais de 256 GB de RAM) essa configuração pode falhar, como quando o SO não consegue alocar uma área contínua para as páginas após o boot. Logo, é mais seguro configurar as huge pages sempre no boot loader, nesse caso, o grub, que é o mais utilizado.

  • Atualizar a alteração: é necessário executar como root ou sudo o comando update-grub e depois reiniciar o servidor com reboot.
Debian shell: atualizando o servidor pós alterações em parâmetros
sudo update-grub
sudo reboot

Transparent Huge Pages

Transparent Huge Pages é uma funcionalidade do kernel Linux que automaticamente gerencia e aloca as huge pages, ajudando o sistema a usar a memória de forma mais eficiente. O ajuste aqui também é recomendado para servidores com bastante RAM, de 32 GB ou mais.

Vantagem: usar páginas maiores facilita o trabalho do sistema ao gerenciar a memória, evita o desperdício de espaço e pode deixar programas que usam muita memória mais rápidos.

Desvantagem: o uso de páginas maiores pode causar problemas se o sistema precisar frequentemente converter páginas menores em páginas grandes. Esse processo de conversão pode gerar atrasos e sobrecarga adicional, especialmente em cargas de trabalho intensivas, o que pode prejudicar o desempenho em vez de melhorá-lo. 

Praticamente todos os bancos de dados relacionais, incluindo o PostgreSQL, sofrem uma piora na performance quando usam o THP, logo, é padrão desabilitá-lo.

Configuração:

Para ver se o THP está ativado, você pode usar este comando:

Debian shell: checando THP
~$ cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never

Nessa saída, vemos que a funcionalidade está ativa de forma geral no sistema (pelo always selecionado). As outras duas opções representam:

  • madvise: só é ativado para programas que solicitam explicitamente o uso de páginas grandes, através de uma chamada ao sistema madvise. Esse é um modo intermediário, no qual o THP não é usado em todas as situações, mas apenas quando recomendado;
  • never: o THP está desativado.

Se você quiser desativar o THP temporariamente (até reiniciar o sistema), use o seguinte comando:

Debian shell: desativando THP temporariamente
echo "never" | sudo tee /sys/kernel/mm/transparent_hugepage/enabled

Já para desativá-lo permanentemente, o que traz um desempenho e uma performance mais consistentes e ideais para um servidor de banco de dados, basta adicionar o script abaixo no arquivo /etc/rc.local:

Debian shell: desativando THP permanentemente
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
    echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
    echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi

Limits

São configurações que determinam o uso máximo de recursos do sistema para processos e usuários. Os limits ajudam a controlar o consumo de recursos e a evitar que um único processo ou usuário sobrecarregue o sistema.

Anteriormente, os limits de recursos eram configurados diretamente no arquivo /etc/security/limits.conf. No entanto, as versões mais recentes do sistema operacional Linux permitem que essas configurações sejam organizadas em arquivos específicos dentro do diretório /etc/security/limits.d/, o que facilita a gestão e a organização das configurações.

Por exemplo, no caso do PostgreSQL, o arquivo /etc/security/limits.d/90-postgresql.conf pode ser utilizado para definir os limits de recursos específicos para o usuário postgres. Esses arquivos são organizados e aplicados por ordem alfanumérica, o que significa que faz diferença escolher um número (como o 90) no momento de nomear seu arquivo.

Exemplo de configuração

Um parâmetro comum a ser configurado quando utilizamos grandes bancos de dados é o nofile, que define o número máximo de arquivos que um processo pode abrir ao mesmo tempo. No PostgreSQL, essa configuração é crucial para evitar erros relacionados ao excesso de arquivos abertos. Alguns dos erros comuns relacionados a esse parâmetro são:

Debian shell: erro de carga de arquivos
LOG: out of file descriptors: Too many open files in system; release and retry 
PANIC: could not open file (...): Too many open files in system

Para resolver, basta ajustar o parâmetro nofile dentro do arquivo 90-postgresql.conf:

Debian shell: ajustando parâmetro nofile
postgres soft nofile 65535
postgres hard nofile 65535

Na primeira linha, definimos o soft limit ou limite suave (valor que o sistema mantém, mas que pode ser alterado pelo próprio usuário, sem ultrapassar o hard limit) para o número de arquivos abertos pelo usuário postgres, como 65.535 arquivos.

Já na segunda linha, foi definido o hard limit ou limite rígido (valor que só pode ser alterado por usuários com permissões elevadas) para o número de arquivos abertos pelo usuário postgres, também como 65.535 arquivos. Esse valor costuma ser adequado para a maioria dos bancos de dados grandes.

Conclusão

Apesar da eficiência natural do PostgreSQL, ambientes críticos e pesados beneficiam-se muito de pequenos ajustes no Linux e melhoram o desempenho, a segurança e o bom uso dos recursos do hardware. 

Quanto mais você conhecer o tipo de carga do seu banco de dados, melhor poderá ajustar a arquitetura do seu servidor e as configurações do Linux. Este artigo mostra as opções mais comuns, utilizadas em todos os servidores de produção com os quais trabalhamos e recomendadas após uma longa experiência no assunto. No entanto, situações extremas podem se beneficiar de ajustes específicos que fogem do escopo deste artigo. De qualquer forma, com as sugestões apresentadas aqui, você certamente estará em boas mãos na maior parte dos casos.

Compartilhe

Você pode gostar

pg_hba.conf

Introdução O arquivo pg_hba.conf (PostgreSQL Host-Based Authentication) é uma peça fundamental na configuração de segurança de qualquer instância PostgreSQL. Ele define as regras de autenticação

Tipos de cargas dos bancos de dados

Introdução Cargas de dados referem-se aos diferentes tipos de operações e transações que um banco de dados deve processar. Essas cargas variam conforme o tipo

Catálogo do sistema (pg_catalog)

Introdução O pg_catalog é um schema especial no PostgreSQL que guarda todos os segredos do seu banco de dados. Quer saber como suas tabelas são

plugins premium WordPress