Noções Básicas de Gerenciamento de Mudanças
8 exemplos para você começar com o gerenciamento de mudanças do Postgres - 5 básicos e 3 intermediários.
Pré-requisitos
# Migrações executadas através da sua ferramenta padrão com revisão
flyway -url="$DATABASE_URL" info
# ou
liquibase --changelog-file=db/changelog.xml status- Uma matriz de risco de DDL escrita no repositório
docs/ourunbooks/. - Volume de dados de staging dentro de 10x das contagens de linhas de produção para testes de bloqueio realistas.
- Aprovação CAB ou assíncrona para mudanças de alto risco de acordo com seu nível de conformidade.
Exemplos Básicos
1. Matriz de Nível de Risco de DDL
Atribua um nível a cada migração antes do merge.
| Nível | Exemplos | Aprovação | Janela |
|---|---|---|---|
| Baixo | CREATE INDEX CONCURRENTLY, adicionar coluna anulável | Revisão de PR | A qualquer momento |
| Médio | Backfill NOT NULL, novo FK com NOT VALID | Líder de equipe + DBA | Horário comercial |
| Alto | ALTER TYPE, reescrita de tabela, anexo de partição | DBA + CAB | Janela de manutenção |
| Digno de Sev | pg_upgrade, migração de armazenamento principal | Executivo + aprovação de DR | Janela dedicada |
- Marque scripts Flyway/Liquibase com
-- risk: mediumem comentários de cabeçalho. - Bloqueie o deploy se o nível exceder a política atual da janela.
Relacionado: Melhores Práticas de Gerenciamento de Mudanças - checklist de aplicação
2. Proteção de Timeout de Bloqueio em Migrações
Evite que as migrações esperem para sempre por bloqueios.
-- Definir no início da sessão de migração (callback Flyway ou pre-sql Liquibase)
SET lock_timeout = '5s';
SET statement_timeout = '30min';
SET idle_in_transaction_session_timeout = '5min';
ALTER TABLE orders ADD COLUMN IF NOT EXISTS priority smallint;- Falha no timeout de bloqueio aborta rapidamente em vez de congelar o checkout.
- Tente novamente migrações de risco médio em uma janela mais tranquila.
- Registre falhas de timeout de bloqueio no ticket de mudança automaticamente.
3. Fase de Expansão: Adicionar Coluna Anulável
Primeiro passo seguro de expandir/contrair.
-- Expansão: adicionar coluna (instantâneo no PostgreSQL 11+ para valor padrão nulo anulável)
ALTER TABLE customers ADD COLUMN IF NOT EXISTS tier text;
-- Deploy da aplicação escreve o tier apenas em novas linhas (feature flag)
-- Backfill em lotes
UPDATE customers SET tier = 'standard' WHERE tier IS NULL AND id BETWEEN 1 AND 10000;- Nunca adicione
NOT NULLsem um valor padrão em uma única etapa em tabelas grandes. - Lote
UPDATEcom intervalos de chave primária para evitar bloqueios longos. - Monitore o atraso de replicação durante o backfill.
4. Fase de Contração: Remover Coluna Não Utilizada
Somente depois que o código não ler mais a coluna.
-- Verifique zero leituras em pg_stat_user_tables (aproximado) e métricas da aplicação
SELECT relname, seq_scan, idx_scan FROM pg_stat_user_tables WHERE relname = 'customers';
-- Contração
ALTER TABLE customers DROP COLUMN IF EXISTS legacy_code;- Regra de duas versões: implante código que ignora a coluna, depois remova a coluna.
- Faça backup lógico ou garanta PITR antes de remoções de alto risco.
5. Modelo de Ticket de Mudança
Cada DDL de produção vincula evidências.
## CHG-2044 Adicionar orders.priority
- Nível de risco: Médio
- Migração: V2044__orders_priority.sql
- Raio de explosão: tabela orders (42M linhas), serviço de checkout
- Rollback: DROP COLUMN priority (após reverter a aplicação)
- Teste de bloqueio: passou em staging em 2026-07-08
- Consciente do plantão: sim- Anexe
EXPLAINpara qualquer novo índice. - Anote a duração esperada do cronômetro de staging.
Relacionado: Janelas de Manutenção - quando agendar
Exemplos Intermediários
6. Padrão de Chave Estrangeira NOT VALID
Adicione aplicação sem bloquear escritas em linhas existentes.
ALTER TABLE line_items
ADD CONSTRAINT line_items_order_id_fkey
FOREIGN KEY (order_id) REFERENCES orders(id)
NOT VALID;
-- Valide mais tarde em uma janela menor (ainda leva ShareUpdateExclusiveLock)
ALTER TABLE line_items VALIDATE CONSTRAINT line_items_order_id_fkey;NOT VALIDadiciona apenas metadados; linhas ruins existentes permanecem até a validação.- Execute a limpeza de dados antes de
VALIDATE CONSTRAINT. - Documente a consulta de linhas órfãs no ticket.
7. Adição de Índice Zero-Downtime
Construção concorrente para tabelas OLTP.
CREATE INDEX CONCURRENTLY IF NOT EXISTS orders_customer_id_idx
ON orders (customer_id);
-- Flyway: desativar o wrapper de transação para este script# Verificar índice válido
psql -c "SELECT indisvalid FROM pg_index WHERE indexrelid = 'orders_customer_id_idx'::regclass;"- Índices concorrentes inválidos exigem
REINDEX CONCURRENTLY(veja solução de problemas). - Não envolva
CREATE INDEX CONCURRENTLYem um bloco de transação.
8. Mudança Digna de Sev: Upgrade de Versão Principal
Trate pg_upgrade como um lançamento de produto, não um patch.
## Pré-voo
- [ ] Backup lógico + checkpoint PITR verificado
- [ ] Matriz de compatibilidade de extensão (pgvector, PostGIS)
- [ ] Rollback = manter cluster antigo parado, reverter DNS
- [ ] String de conexão da aplicação testada em PG 18.4 staging- Execute
pg_upgrade --checkem um clone primeiro. - Reserve 2x a janela esperada para o primeiro upgrade principal na equipe.
Relacionado: Antes/Depois: Upgrade de Versão Principal - referência narrativa
Versões da 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+.