postgres postgresql database db

Bancos de dados

Como visto antes, uma instância do PostgreSQL é a unidade sobre a qual operamos para fins de administração de sistemas, como monitoramento, replicação, autenticação e backup. Contudo, essa não é a granularidade adequada para os fins da aplicação, que tem um interesse mais voltado à manipulação (armazenamento e consulta) dos dados.

Um banco de dados é uma segmentação tanto física quanto lógica da instância, destinada a um propósito único, como atender uma aplicação específica. Isso significa que os dados são armazenados fisicamente em outros diretórios (segmentação física) e que conexões são estabelecidas com exatamente um banco de dados e não têm acesso aos dados de outros bancos de dados (segmentação lógica).

Podem ser criados objetos locais dentro de um banco de dados, como tabelas, visões, índices e sequências. Contudo, objetos globais, como usuários, tablespaces, slots de replicação e outros bancos de dados, apesar de poderem ser criados através de uma conexão com um banco de dados, não são criados dentro daquele banco de dados, mas sim na instância.

                     ┌───────────────────┐
╔════════════════════╡ 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├┘    ║     ║        │          ║
╚════════════════════════════════════╩═════╩════════╪══════════╝
                                                    │
                                                    ↓
                                                 ╔╡/…╞╗
                                                 ║    ║
                                                 ╚════╝

postgres, template1 e template0

É necessário que exista um banco de dados e um usuário para que a autenticação permita a nova conexão. É necessária uma conexão ativa para criar um banco de dados e um usuário. Para quebrar esse impasse de galinha-e-ovo, toda nova instância é criada automaticamente com um banco de dados chamado postgres e um usuário com permissão SUPERUSER (este com nome igual ao usuário que executou o initdb, normalmente também postgres).

O propósito do usuário postgres e do banco de dados postgres é, portanto, permitir que outros usuários e bancos de dados sejam criados. É recomendado que eles não sejam usados para outros fins, mas sim que outros usuários (com permissões reduzidas) e bancos de dados sejam usados para atender as diversas aplicações, assim como atividades de backup, monitoramento e replicação.

Ao criar um novo banco de dados, o PostgreSQL sempre copia um modelo pré-existente. Quando o modelo não é informado, o template1 é usado. Isso não só traz agilidade na criação de bancos de dados, como também permite que o usuário customize os modelos, adicionando objetos e dados que são importados em todo novo banco de dados e economizando tempo de criá-los em todo novo banco de dados.

O terceiro banco de dados criado com a inicialização da instância é o template0, que atende dois propósitos. Por um lado, ele pode ser usado para recriar o template1 se as customizações deste precisarem ser descartadas. Por outro, o template0 é o único banco de dados com a codificação de caracteres indefinida e, por essa razão, quando é copiado, uma codificação pode ser escolhida para o novo banco de dados.

IMPORTANTE: Note que a codificação recomendada para todos os propósitos no servidor é UTF8 (outras são mantidas para compatibilidade com o passado); e a aplicação deve configurar client_encoding para cada conexão, assim conversões entre codificações de cliente e servidor são feitas de forma transparente e confiável.

Listagem dos bancos de dados existentes, com seus respectivos donos, codificações, privilégios, tamanhos e outras propriedades:

[[local]:5432] postgres@postgres=# \l+
                                                                 List of databases
╔═══════════╤═══════════╤══════════╤═════════╤═════════╤═══════════════════════╤═════════╤════════════╤════════════════════════════════════════════╗
║   Name    │   Owner   │ Encoding │ Collate │  Ctype  │   Access privileges   │  Size   │ Tablespace │                Description                 ║
╠═══════════╪═══════════╪══════════╪═════════╪═════════╪═══════════════════════╪═════════╪════════════╪════════════════════════════════════════════╣
║ postgres  │ postgres  │ UTF8     │ C.UTF-8 │ C.UTF-8 │                       │ 8097 kB │ pg_default │ default administrative connection database ║
║ template0 │ postgres  │ UTF8     │ C.UTF-8 │ C.UTF-8 │ =c/postgres          ↵│ 7841 kB │ pg_default │ unmodifiable empty database                ║
║           │           │          │         │         │ postgres=CTc/postgres │         │            │                                            ║
║ template1 │ postgres  │ UTF8     │ C.UTF-8 │ C.UTF-8 │ postgres=CTc/postgres↵│ 7953 kB │ pg_default │ default template for new databases         ║
║           │           │          │         │         │ =c/postgres           │         │            │                                            ║
╚═══════════╧═══════════╧══════════╧═════════╧═════════╧═══════════════════════╧═════════╧════════════╧════════════════════════════════════════════╝

Propriedades dos bancos de dados

É possível impedir conexões novas a um banco de dados alterando a propriedade ALLOW_CONNNECTIONS, mas conexões já estabelecidas permanecem, podendo ser fechadas com pg_terminate_backend():

[[local]:5432] postgres@postgres=# ALTER DATABASE app ALLOW_CONNECTIONS FALSE;

Também é possível limitar quantas conexões um banco de dados terá estabelecidas a todo momento:

[[local]:5432] postgres@postgres=# ALTER DATABASE app CONNECTION LIMIT 5;

Por padrão, apenas usuários com a permissão de SUPERUSER podem usar todos os bancos de dados como modelos na criação de novos bancos de dados. Mas podemos marcar bancos de dados específicos com a propriedade IS_TEMPLATE para que todo usuário com permissão CREATEDB possa usar aquele banco de dados como modelo:

[[local]:5432] postgres@postgres=# ALTER DATABASE modelo IS_TEMPLATE TRUE;

Prática

Criando um banco de dados

[[local]:5432] postgres@postgres=# CREATE DATABASE app;

Criando um banco de dados de modelo com uma tabela

[[local]:5432] postgres@postgres=# CREATE DATABASE modelo_app;
[[local]:5432] postgres@postgres=# \c modelo_app
[[local]:5432] postgres@modelo_app=# CREATE TABLE tabela ();
[[local]:5432] postgres@modelo_app=# \d
         List of relations
╔════════╤════════╤═══════╤══════════╗
║ Schema │  Name  │ Type  │  Owner   ║
╠════════╪════════╪═══════╪══════════╣
║ public │ tabela │ table │ postgres ║
╚════════╧════════╧═══════╧══════════╝

Criando um banco de dados a partir de um modelo

[[local]:5432] postgres@postgres=# CREATE DATABASE app TEMPLATE modelo_app;
[[local]:5432] postgres@postgres=# \c app
[[local]:5432] postgres@app=# \d
         List of relations
╔════════╤════════╤═══════╤══════════╗
║ Schema │  Name  │ Type  │  Owner   ║
╠════════╪════════╪═══════╪══════════╣
║ public │ tabela │ table │ postgres ║
╚════════╧════════╧═══════╧══════════╝

Destruindo um banco de dados

[[local]:5432] postgres@postgres=# DROP DATABASE modelo_app;
[[local]:5432] postgres@postgres=# DROP DATABASE app;