Banco de Dados, Schema e Caminho de Busca
Um banco de dados é um catálogo isolado de schemas. Um schema organiza tabelas e funções em namespaces. O search_path controla como nomes não qualificados são resolvidos. Bugs de produção frequentemente surgem de caminhos ambíguos, não de tabelas ausentes.
Receita
SHOW search_path;
ALTER ROLE app_user SET search_path = app, public;
-- Prefira qualificação explícita em migrações
CREATE TABLE app.orders (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
customer_id bigint NOT NULL REFERENCES app.customers(id)
);Quando usar isso: Você projeta bancos de dados multi-aplicativos, clusters compartilhados ou padrões específicos de role.
Exemplo de Trabalho
CREATE SCHEMA billing AUTHORIZATION postgres;
CREATE SCHEMA reporting AUTHORIZATION postgres;
CREATE TABLE billing.invoices (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
amount numeric(12,2) NOT NULL CHECK (amount >= 0)
);
CREATE VIEW reporting.invoice_totals AS
SELECT date_trunc('month', now()) AS month, sum(amount) AS total
FROM billing.invoices;
SET search_path = reporting, billing;
SELECT * FROM invoice_totals;O que isso demonstra:
- Múltiplos schemas coexistem em um banco de dados com referências entre schemas.
- Views podem residir em um schema diferente das tabelas base.
- A ordem do
search_pathdetermina qual objeto tem precedência para nomes não qualificados.
Mergulho Profundo
Ordem de Resolução
- O PostgreSQL verifica os schemas listados no search_path da esquerda para a direita.
- Tabelas temporárias residem em schemas pg_temp adicionados no início para a sessão.
- Catálogos do sistema são sempre acessíveis via pg_catalog.
Padrões de Role e Banco de Dados
ALTER DATABASE ... SET search_pathaplica-se na conexão, a menos que a role substitua.ALTER ROLE ... SET search_pathé comum para roles de aplicação.- Migrações devem definir um caminho explícito no topo:
SET search_path = app;
Nota de Segurança
- Objetos em public são criáveis por padrão em muitas instalações (privilégio
CREATEparaPUBLIC). - Proteja o schema
publicou use schemas dedicados com concessões de privilégio mínimo.
Armadilhas
publicé uma armadilha - Qualquer role pode criar objetos que sombreiam tabelas de aplicativos. Correção:REVOKE CREATE ON SCHEMA public FROM PUBLIC;use schemas dedicados.- Nomes não qualificados duplicados -
app.usersearchive.usersambos nomeadosusers. Correção: Qualifique o schema no SQL enviado pelos aplicativos. search_pathem funçõesSECURITY DEFINER- Direitos de definidor mais um caminho mutável permitem sequestro. Correção:SET search_path = pg_temp, pg_catalog;em funções definidoras.- Ordem de dump/restore - Schemas devem existir antes dos objetos que os referenciam. Correção: Use transação única do
pg_dumpou ferramentas de DDL ordenado. - Dobramento de caixa (Case folding) - Identificadores não citados são convertidos para minúsculas. Correção: Use aspas apenas quando necessário; prefira
snake_case.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Um schema por microsserviço | Clareza de propriedade em um DB compartilhado | Muitos schemas para conceder e migrar |
| Banco de dados por serviço | Isolamento forte | Mais conexões e sobrecarga operacional |
| Segurança em nível de linha (Row-level security) | Tabelas compartilhadas com tenant_id | Complexidade de política e testes de performance |
FAQs
Quantos schemas são muitos?
Centenas são aceitáveis. A complexidade vem das concessões e da ordem de migração, não do custo de OID.
Duas bases de dados podem compartilhar um nome de schema?
Nomes de schema são por banco de dados. O mesmo nome em bancos de dados diferentes não está relacionado.
O que é o schema $user?
Um placeholder para um schema que corresponde ao nome da role; frequentemente vazio.
Extensões devem viver em `public`?
Muitas instalações usam public. Algumas equipes dedicam um schema de extensões.
O `search_path` afeta operadores?
Sim, para tipos e funções resolvidos para chamadas não qualificadas.
Relacionado
- Noções Básicas de PostgreSQL - criar schema e tabela
- Noções Básicas de Roles - padrões GUC em nível de role
- Riscos do SECURITY DEFINER - armadilhas do
search_path
Versões do Stack: Esta página foi escrita para PostgreSQL 18.4 (estável 18, manutenção 17), pgvector 0.8+, PgBouncer 1.x, Patroni 3.x, e PostGIS 3.5+.