postgres postgresql init initdb
Uma instância, ou cluster, é um agrupamento de bancos de dados controlados por um SGBD (Sistema de Gerenciamento de Banco de Dados). Ela também contém objetos globais, como usuários e tablespaces, assim como arquivos de configuração. É sobre as instâncias (não sobre seus bancos de dados) que fazemos backups, restaurações, replicações físicas, monitoramento e diversas outras atividades de administração do sistema.
Obs.: A nomenclatura cluster é histórica e foi introduzida pelo padrão SQL na década de 80. O PostgreSQL tenta se manter o mais próximo possível do padrão SQL, por isso usa essa nomenclatura. Mas outros SGBDs costumam chamar o mesmo conceito de instância. Outros chamam de instância o processo que controla o grupo. Para evitar confusões do termo cluster em outros contextos, vou usar o termo instância a partir de agora para significar o grupo de bancos de dados.
┌───────────────────┐ ╔════════════════════╡ instância/cluster ╞═════════════════════╗ ║ └───────────────────┘ ║ ╠═╡global/╞═══════╗ ╔═════════════════════════════════╡base/╞═╣ ║ ║ ║ ║ ║ O O ║ ║ ┏┥banco de dados┝┓ ┏━┥banco de dados┝━┓ ║ ║ ─┼─ ─┼─ ║ ║ ┃└┤postgres├────┘┃ ┃ ┌─┤schema├─────┐ ┃ ║ ║ │ │ ║ ║ ┗━━━━━━━━━━━━━━━━┛ ┃ │ ☑ tabelas │ ┃ ║ ║ ╱ ╲ ╱ ╲ ║ ║ ┏┥banco de dados┝┓ ┃ │ ☑ índices │ ┃ ║ ║ ☑ usuários ║ ║ ┃└┤template1├───┘┃ ┃ │ ☑ visões │ ┃ ║ ║ ☑ grupos ║ ║ ┗━━━━━━━━━━━━━━━━┛ ┃ │ ☑ sequências │ ┃ ║ ║ ☑ slots de ║ ║ ┏┥banco de dados┝┓ ┃ │ ☑ … │ ┃ ║ ║ ☑ replicação ║ ║ ┃└┤template0├───┘┃ ┃ └──────────────┘ ┃ ║ ║ ☑ pg_control ║ ║ ┗━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━┛ ║ ║ ║ ║ ║ ╠═════════════════╝ ╚═════════════════════════════════════════╣ ║ ║ ╠═╡pg_wal/╞══════════════════════════╗ ╔══════╡pg_tblspc/╞═╣ ║ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ║ ║ ║ ║ │…++++│→│…++++│→│…++++│→│…++++│→… ║ ║ ║ ║ └┤/…1├┘ └┤/…2├┘ └┤/…3├┘ └┤/…4├┘ ║ ║ │ ║ ╚════════════════════════════════════╩═════╩════════╪══════════╝ │ ↓ ╔╡/…╞╗ ║ ║ ╚════╝
Todo PostgreSQL nasce com a inicialização do diretório de dados (também conhecido como datadir ou PGDATA), que hospeda a instância. Ele contém subdiretórios para cada banco de dados, assim como subdiretórios para objetos globais, arquivos de configuração, regras de autenticação, logs textuais, logs de transação e outros.
Exemplo de diretório de dados recém iniciado:
datadir ├── PG_VERSION ├── base │ ├── 1 │ ├── 13754 │ └── 13755 ├── global │ ├── ⋮ │ ├── pg_control │ └── pg_filenode.map ├── pg_commit_ts ├── pg_dynshmem ├── pg_hba.conf ├── pg_ident.conf ├── pg_logical │ ├── mappings │ ├── replorigin_checkpoint │ └── snapshots ├── pg_multixact │ ├── members │ └── offsets ├── pg_notify │ └── 0000 ├── pg_replslot ├── pg_serial ├── pg_snapshots ├── pg_stat ├── pg_stat_tmp ├── pg_subtrans │ └── 0000 ├── pg_tblspc ├── pg_twophase ├── pg_wal │ ├── 000000010000000000000001 │ └── archive_status ├── pg_xact │ └── 0000 ├── postgresql.auto.conf ├── postgresql.conf └── postmaster.pid
Alguns dos conteúdos mais interessantes são:
- PG_VERSION: versão majoritária da instância
- base: diretório de bancos de dados, com um subdiretório por banco de dados
- postgresql.conf e postgresql.auto.conf: arquivos de configuração
- pg_hba.conf: arquivo com definições de autenticação
- pg_tblspc: diretório de tablespaces, contendo apenas links simbólicos para outros diretórios
- pg_wal: diretório de segmentos de WAL, necessários para recuperação de desastres
- pg_control: arquivo de controle, com informações vitais de instância, como timeline, lsn e xact
- postmaster.pid: arquivo com pid e outros dados do serviço em execução (ATENÇÃO: nunca apague ele)
- …
Em alguns casos é útil, e até mesmo necessário, que uma máquina hospede mais de
uma versão do PostgreSQL (binário e diretório de dados), por exemplo durante um
upgrade por pg_upgrade
.
Por isso, a instalação do PostgreSQL pelo repositório do PGDG usa diretórios
diferenciados pela versão, tanto para os binários, quanto para os dados. Por
exemplo, em CentOS o diretório de binários é /usr/pgsql-<versão>/bin
e o
diretório de dados é /var/lib/pgsql/<versão>/data
.
Adicionalmente, também é possível instanciar mais de um PostgreSQL da mesma versão majoritária usando diretórios e portas diferentes para cada. Mas esse caso de uso é menos comum.
Em Debian, o diretório de binários é /usr/lib/postgresql/<versão>
e os
diretórios de dados são /var/lib/postgresql/<versão>/<instância>
, sendo que
main
é o nome padrão da instância criada automaticamente. Para ajudar a
gerenciar a escolha de diretório e de portas para novas instâncias, Debian e
derivados disponibilizam scripts de conveniência mais complexos, que exigem o
fornecimento da versão e identificador da instância.
postgres@pg-1:~$ pg_createcluster 16 outro
Em CentOS, é necessário inicializar o diretório de dados, alterar a porta e duplicar o arquivo de serviço.
Primeiro, inicializando um outro diretório de dados:
[postgres@pg-1 ~]$ /usr/pgsql-16/bin/initdb -D /var/lib/pgsql/16/outro
Então alterando a porta de /var/lib/pgsql/16/outro/postgresql.conf.
Duplicando o arquivo de serviço e apontando para outro diretório:
[root@pg-1 ~]$ cp /usr/lib/systemd/system/postgresql-16.service /etc/systemd/system/postgresql-16-outro.service [root@pg-1 ~]$ systemctl daemon-reload [root@pg-1 ~]$ systemctl set-property postgresql-16-outro.service Environment=PGDATA=/var/lib/pgsql/16/outro
O comando usado para inicializar a instância é o initdb
. Como o conteúdo do
diretório tem arquivos com estruturas específicas da versão majoritária, é vital
usar o initdb
da mesma versão que o servidor. Portanto, esse executável, assim
como outros de nível de servidor, costuma ser encontrado em um diretório
versionado.
Além do initdb
, algumas distribuições disponibilizam scripts de conveniência
que primeiro inicializam a instância e então iniciam ou habilitam o respectivo
serviço do PostgreSQL.
Inicialização pelo script de conveniência, como root:
[root@pg-1 ~]# /usr/pgsql-16/bin/postgresql-16-setup initdb
Inicialização pelo initdb
, como postgres:
[postgres@pg-1 ~]$ /usr/pgsql-16/bin/initdb -D /var/lib/pgsql/16/data
Inicialização pelo script de conveniência, como root ou postgres:
postgres@pg-1:~$ pg_createcluster 16 main
Inicialização pelo initdb
, como postgres:
postgres@pg-1:~$ /usr/lib/postgresql/16/initdb -D /var/lib/postgresql/16/main
ATENÇÃO: O script de conveniência irá criar o diretório de dados em
/var/lib/postgresql/<versão>/<instância>
mas com os arquivos de configuração
em /etc/postgresql/<versão>/<instância>
. Isso tem a intenção de separar dados
em /var
e configurações em /etc
, mas dificulta algumas tarefas posteriores,
como backup e replicação.