Arquivos, diretórios e processos

Introdução

No PostgreSQL, a organização de arquivos e diretórios, bem como a gestão de processos, são componentes fundamentais para entender o seu funcionamento. Este artigo fornecerá uma visão geral de como o PostgreSQL estrutura seus dados e controla seus processos.

Roteiro:

  • Arquivos e diretórios dos dados no PostgreSQL:
    • Binários
    • Arquivos de configuração
    • Arquivos de logs
    • Subdiretórios
  • Processos

Arquivos e diretórios dos dados no PostgreSQL

O PostgreSQL organiza seus dados e configurações em uma estrutura de diretórios específica. A localização desses diretórios pode variar dependendo da instalação, mas geralmente segue um padrão. O diretório principal que contém todos os dados do PostgreSQL é o Base Directory (também conhecido pela variável de ambiente $PGDATA), que é definido durante a inicialização do cluster PostgreSQL com o comando initdb. Para sistemas Linux, o endereço de PGDATA pode variar conforme a distribuição:

  • Debian: /var/lib/postgresql/<versão>/<nome_do_cluster>
  • Red Hat: /var/lib/pgsql/<versão>/data

Claro, você pode definir qualquer diretório/disco/partição para colocar seus dados, como demonstramos nos artigos anteriores sobre instalação. Portanto é uma boa ideia usar a variável de ambiente $PGDATA (que, a depender da distribuição, já vem setada para o usuário postgres) ou então descobrir esse diretório pelo comando no psql SHOW data_directory:

psql shell: consultando o diretório de dados
$ psql -c 'SHOW data_directory;'
       data_directory
-----------------------------
 /var/lib/postgresql/16/main
(1 row)

Nesse diretório, temos arquivos e subdiretórios importantes para o programa, que veremos a seguir.

Binários

Dentre os principais arquivos do PostgreSQL, temos os binários, que são executáveis responsáveis por iniciar e interagir com o banco de dados. Eles estão em diferentes diretórios, que mudam conforme o sistema operacional. Considerando essas três distribuições Linux, podemos encontrar os principais binários em:

  • Debian:
    • /usr/share/postgresql-common: contém arquivos e scripts comuns utilizados por várias versões do PostgreSQL, por exemplo, pg_ctlcluster e pg_createcluster;
    • /usr/lib/postgresql/<sua_versão>/bin: neste diretório, você pode encontrar os binários específicos da versão do PostgreSQL, como o próprio psql, os utilitários createdb, initdb etc.
  • Red Hat:
    • /usr/pgsql/<versão>/bin/: guarda binários e executáveis específicos de cada versão do PostgreSQL.
  • Instalação via compilação:
    • /usr/local/pgsql/bin/

Arquivos de configuração

  • postgresql.conf: principal arquivo de configuração do servidor PostgreSQL. Contém parâmetros para ajustar o desempenho, a segurança, o comportamento e outras opções do servidor. Em distribuições Debian e derivados, este arquivo está em outro local, num diretório que agrega todos os arquivos de configuração: /etc/postgresql/<versão>/<nome_do_cluster>;
  • pg_hba.conf: configurações de autenticação do host. Define quem pode conectar-se ao banco de dados e como as conexões são autenticadas. Assim como antes, em distribuições Debian e derivados, este arquivo fica em outro local;
  • pg_ident.conf: mapeamentos para autenticação do tipo ident no pg_hba.conf. Usado para mapear nomes de usuários do sistema operacional para nomes de usuários do PostgreSQL. Mais uma vez, em distribuições Debian e derivados, este arquivo fica em outro local, vide acima;
  • postgresql.auto.conf: armazena as configurações definidas dinamicamente através do comando ALTER SYSTEM SET, bem como outras configurações definidas automaticamente pelo próprio PostgreSQL. Você não deve editar este arquivo manualmente!;
  • PG_VERSION: contém a versão do PostgreSQL em uso no cluster (major version);
  • postmaster.pid: contém o ID do processo (PID) do servidor PostgreSQL em execução e outras informações, como diretório de dados do cluster, data de início do processo etc.;
  • postmaster.opts: arquivo que registra as opções de linha de comando usadas por último na inicialização do servidor PostgreSQL.

Arquivos de logs

Dentro do $PGDATA, temos outros diretórios importantes que guardam arquivos do PostgreSQL, como os arquivos de log. Normalmente, os logs ficam em $PGDATA/logs, mas em distribuições Debian e derivadas eles estão localizados em /var/log/postgresql, como podemos ver na saída abaixo. 

Debian shell: logs do PostgreSQL
# ls -lh /var/log/postgresql/*
total 6.6M
drwxrwxr-t  2 root     postgres 4.0K May 19 00:00 .
drwxr-xr-x 10 root     root     4.0K May  1 00:00 ..
-rw-r-----  1 postgres adm      123K May 23 09:40 postgresql-16-main.log
-rw-r-----  1 postgres adm      6.0M May 19 00:00 postgresql-16-main.log.1
-rw-r-----  1 postgres adm      254K May 12 00:00 postgresql-16-main.log.2.gz
-rw-r-----  1 postgres adm       18K May  5 00:00 postgresql-16-main.log.3.gz
-rw-r-----  1 postgres adm      125K Apr 28 00:00 postgresql-16-main.log.4.gz
-rw-r-----  1 postgres adm       27K Apr 21 00:00 postgresql-16-main.log.5.gz
-rw-r-----  1 postgres adm       36K Apr 14 00:00 postgresql-16-main.log.6.gz
-rw-r-----  1 postgres adm      1.1K Apr  7 00:00 postgresql-16-main.log.7.gz
-rw-r-----  1 postgres adm      2.0K Mar 31 00:00 postgresql-16-main.log.8.gz

Na verdade, você pode escolher outros lugares arbitrários para colocar seus logs, como em um disco separado (pode ser útil em servidores com muita carga), ajustando a variável log_directory. Abaixo vemos um exemplo da localização do diretório de logs na AWS RDS:

psql: consultando o diretório de logs em um banco AWS RDS
SHOW log_directory;
    log_directory
----------------------
 /rdsdbdata/log/error

O valor do log_directory pode ser absoluto, com o path completo ou relativo ao diretório do $PGDATA.

Subdiretórios

  • base/: contém um subdiretório para cada banco de dados individual no cluster;
    • Dentro desses subdiretórios de cada banco que são identificados com números (16390, por exemplo) temos com os dados de cada objeto no banco, como tabelas e índice. Estes arquivos possuem eventualmente outros com o mesmo número e um sufixo _fsm (free space map) e _vm (visibility map), que são essenciais para manutenção e otimização e controle de transações. Além disso, temos um diretório chamado pgsql_tmp com arquivos temporários como tabelas temporárias. Eventualmente é possível armazenar estes arquivos temporários em outros tablespaces, ajustando a configuração temp_tablespaces;
  • global/: contém tabelas e dados globais, como informações sobre usuários e grupos, por exemplo, as tabelas pg_database e pg_control;
    • Aqui também temos os arquivos _fsm e _vm, mas a nível global, ou seja, que se aplicam a todos os bancos de dados em um cluster;
  • pg_xlog/ ou pg_wal/: contém os arquivos de log de transação (WAL – Write-Ahead Logging), essenciais para a recuperação de dados;
  • pg_clog/ ou pg_commit_ts/: mantém informações sobre o estado das transações atuais;
  • pg_stat/: armazena dados estatísticos permanentes utilizados para otimização de consultas;
  • pg_stat_tmp/: armazena dados estatísticos temporários utilizados para otimização de consultas;
  • pg_tblspc/: pontos de montagem de tablespaces, que permitem a administração de locais de armazenamento adicionais.

Processos

PostgreSQL é um sistema de gerenciamento de banco de dados do tipo cliente-servidor. Diferente de outros modelos, ele utiliza uma arquitetura multiprocesso para rodar em um único host. Imagine uma equipe trabalhando em conjunto para cuidar do seu banco de dados: esse é o conceito por trás dessa arquitetura.

Essa “equipe” é composta por diversos processos, cada um com uma função específica:

  • postmaster (server process): o processo principal do PostgreSQL. É responsável por iniciar, parar e supervisionar todos os processos de servidor do PostgreSQL. Ele recebe conexão de apenas uma porta (a 5432 por padrão), porém podemos ter mais de uma instância do PostgreSQL rodando no mesmo servidor, especificando uma porta para cada instância. Podemos ter, por exemplo, um PostgreSQL na versão 16 na porta 5432 e outro na versão 15 na porta 5433;
  • postgres (backend process): cada conexão ao banco de dados é gerenciada por um processo postgres dedicado. Esse processo é responsável por receber e executar as consultas e comandos enviados pelos clientes, garantindo uma experiência personalizada para cada um;
  • autovacuum launcher (background process): processo responsável pela limpeza automática do banco de dados, removendo registros obsoletos gerados por operações de UPDATE e DELETE;
  • wal writer (background process): gerencia a gravação dos logs de transação (WAL) no disco, garantindo a durabilidade das transações, o que permite a recuperação do banco de dados;
  • wal sender (background process): responsável por enviar os registros do WAL (Write-Ahead Logging) do servidor primário para um ou mais servidores de réplica (standby). Este processo é fundamental para a replicação em tempo real e a alta disponibilidade;
  • wal receiver (background process): é executado em servidores de réplica e recebe os registros do WAL enviados pelo processo WAL sender do servidor primário;
  • statistics collector (background process): é responsável por coletar e agrupar estatísticas sobre a operação do banco de dados, como contagem de linhas lidas, inseridas, atualizadas ou deletadas;
  • logging collector (background process): coleta e armazena mensagens de log do servidor PostgreSQL em arquivos de log;
  • archiver (background process): copia os arquivos do WAL para um local de arquivamento seguro após eles serem preenchidos;
  • bgwriter (background process): é o “background writer”, que periodicamente escreve páginas sujas da memória para o disco, ajudando a manter a consistência dos dados;
  • checkpointer (background process): periodicamente cria pontos de verificação (checkpoints) que ajudam na recuperação de falhas;
  • IPC (background process): os processos do PostgreSQL se comunicam usando IPC (Inter-Process Communication), que inclui sinais (signals), memória compartilhada (shared memory) e semáforos (semaphores). Estes mecanismos permitem a coordenação entre os processos, garantindo a consistência e a integridade dos dados.

Abaixo segue o comando ps faux | grep postgres executado como root, que é um comando para mostrar todos os processos relacionados ao postgres, de todos os usuários, e sua saída:

Debian shell: consultando processos postgres
# ps faux | grep postgres
postgres  171711  0.0  1.7 217608 17460 ?        Ss   Apr09   7:52 /usr/lib/postgresql/16/bin/postgres -D /var/lib/postgresql/16/main -c config_file=/etc/postgresql/16/main/postgresql.conf
postgres  171712  0.0  7.8 218036 77644 ?        Ss   Apr09   0:02  \_ postgres: 16/main: checkpointer
postgres  171713  0.0  0.7 217756  7468 ?        Ss   Apr09   0:41  \_ postgres: 16/main: background writer
postgres  171715  0.0  0.6 217608  6796 ?        Ss   Apr09   0:44  \_ postgres: 16/main: walwriter
postgres  171716  0.0  0.7 219208  7108 ?        Ss   Apr09   1:45  \_ postgres: 16/main: autovacuum launcher
postgres  171717  0.0  0.4 219184  4340 ?        Ss   Apr09   0:02  \_ postgres: 16/main: logical replication launcher

Como um exemplo adicional, fizemos um teste com o pg_bench (com escala 10x maior do que a padrão, 50 clientes e quatro threads, com duração de 120 segundos) e rodamos, desta vez, o comando top -c, que fornece a visualização dinâmica e interativa dos processos. Este é um trecho da saída:

Debian shell: consultando processos com teste do pg_bench
# top -c
top - 18:01:38 up 57 days,  2:24,  2 users,  load average: 19.95, 5.63, 1.93
Tasks: 135 total,  32 running, 103 sleeping,   0 stopped,   0 zombie
%Cpu(s): 64.7 us, 34.3 sy,  0.0 ni,  0.0 id,  1.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :    961.0 total,     77.9 free,    505.3 used,    679.6 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.    455.7 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
1219997 postgres  20   0  239676   7792   6412 S  17.5   0.8   0:09.62 /usr/lib/postgresql/16/bin/pgbench -c 50 -j 4 -T 120 postgres
1220014 postgres  20   0  219816  84068  80660 R   2.3   8.5   0:00.92 postgres: 16/main: postgres postgres [local] idle in transaction
1220040 postgres  20   0  219820  82300  78888 S   2.0   8.4   0:00.90 postgres: 16/main: postgres postgres [local] UPDATE waiting
1220050 postgres  20   0  219820  83928  80516 R   2.0   8.5   0:00.90 postgres: 16/main: postgres postgres [local] UPDATE waiting
1220005 postgres  20   0  219816  80776  77376 R   1.7   8.2   0:00.90 postgres: 16/main: postgres postgres [local] COMMIT
1220007 postgres  20   0  219816  82044  78636 S   1.7   8.3   0:00.90 postgres: 16/main: postgres postgres [local] UPDATE waiting
1220009 postgres  20   0  219816  82604  79204 R   1.7   8.4   0:00.90 postgres: 16/main: postgres postgres [local] idle
1220010 postgres  20   0  219816  82204  78804 S   1.7   8.4   0:00.90 postgres: 16/main: postgres postgres [local] UPDATE waiting
1220011 postgres  20   0  219816  81988  78588 R   1.7   8.3   0:00.90 postgres: 16/main: postgres postgres [local] idle in transaction
1220012 postgres  20   0  219816  82944  79544 S   1.7   8.4   0:00.90 postgres: 16/main: postgres postgres [local] UPDATE waiting
1220013 postgres  20   0  219816  83216  79800 R   1.7   8.5   0:00.90 postgres: 16/main: postgres postgres [local] idle in transaction
1220015 postgres  20   0  219816  84092  80692 S   1.7   8.5   0:00.90 postgres: 16/main: postgres postgres [local] UPDATE waiting
1220017 postgres  20   0  219816  80868  77468 R   1.7   8.2   0:00.90 postgres: 16/main: postgres postgres [local] UPDATE waiting
1220018 postgres  20   0  219816  83108  79708 R   1.7   8.4   0:00.90 postgres: 16/main: postgres postgres [local] idle in transaction
1220021 postgres  20   0  219816  83968  80568 S   1.7   8.5   0:00.90 postgres: 16/main: postgres postgres [local] UPDATE waiting
1220022 postgres  20   0  219816  79704  76304 S   1.7   8.1   0:00.90 postgres: 16/main: postgres postgres [local] UPDATE waiting
1220023 postgres  20   0  219816  82652  79252 R   1.7   8.4   0:00.90 postgres: 16/main: postgres postgres [local] idle in transaction
1220024 postgres  20   0  219820  82452  79036 S   1.7   8.4   0:00.90 postgres: 16/main: postgres postgres [local] UPDATE waiting
1220025 postgres  20   0  219820  80704  77292 R   1.7   8.2   0:00.90 postgres: 16/main: postgres postgres [local] COMMIT
1220026 postgres  20   0  219820  79340  75928 R   1.7   8.1   0:00.90 postgres: 16/main: postgres postgres [local] idle in transaction

O primeiro processo pgbench é o que está executando o teste de benchmarking e consome 17,5% da CPU, sendo o responsável pela maior carga no sistema.

Também é possível observar vários processos em estado R (running) ou S (sleeping), o que é esperado em um ambiente de testes. Também temos os status idle in transaction e UPDATE waiting, indicando que estão aguardando a conclusão de transações ou de operações de atualização.

Conclusão

O PostgreSQL tem uma organização relativamente simples de arquivos, diretórios e processos. Para o desenvolvedor ou usuário final do banco de dados, essas informações podem ser mera curiosidade, mas para quem pretende ser um DBA, a história é bem diferente. É fundamental entender o que cada um faz e onde fica cada informação. Enquanto tudo estiver funcionando bem, você provavelmente não vai se preocupar muito com isso, mas quando problemas ocorrerem, como falhas de hardware, bugs etc., entender esses conceitos básicos será fundamental para resolver os problemas. 
Mais informações podem ser encontradas na documentação oficial, aqui.

No próximo artigo, vamos entender um pouco melhor como os objetos do banco são organizados logicamente no catálogo interno e fisicamente nos diretórios $PGDATA/base, $PGDATA/global e $PGDATA/pg_tblspace.

Compartilhe

Você pode gostar

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

Utilização de SQL básico

Introdução Já percorremos um bom caminho até aqui. Instalamos o PostgreSQL em diferentes cenários, vimos algumas ferramentas para utilização no dia a dia, mas você

Utilização do psql

Introdução O psql é a ferramenta de linha de comando padrão para interagir com bancos de dados PostgreSQL, permitindo que você execute consultas SQL, configure

plugins premium WordPress