Testar grátis
9 min leitura Guide 753 of 877

Melhores Práticas de Migração de Banco de Dados

As migrações de banco de dados requerem planejamento e execução cuidadosos. O GitScrum ajuda a rastrear tarefas de migração e coordenar implantações com segurança.

Planejamento de Migração

Estrutura de Tarefa de Migração

HISTÓRIA DE MIGRAÇÃO DE BANCO DE DADOS:
┌─────────────────────────────────────────────────────────────┐
│ DB-123: Adicionar Tabela user_preferences                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│ PROPÓSITO:                                                  │
│ Armazenar preferências de notificação e exibição do usuário│
│ Necessário para: USER-456 (funcionalidade de configurações)│
│                                                             │
│ ═══════════════════════════════════════════════════════════ │
│                                                             │
│ SCRIPT DE MIGRAÇÃO:                                         │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ CREATE TABLE user_preferences (                         ││
│ │   id BIGSERIAL PRIMARY KEY,                            ││
│ │   user_id BIGINT NOT NULL REFERENCES users(id),        ││
│ │   preference_key VARCHAR(100) NOT NULL,                ││
│ │   preference_value JSONB NOT NULL DEFAULT '{}',        ││
│ │   created_at TIMESTAMP DEFAULT NOW(),                  ││
│ │   updated_at TIMESTAMP DEFAULT NOW(),                  ││
│ │   UNIQUE(user_id, preference_key)                      ││
│ │ );                                                      ││
│ │                                                         ││
│ │ CREATE INDEX idx_user_prefs_user ON                    ││
│ │   user_preferences(user_id);                           ││
│ └─────────────────────────────────────────────────────────┘│
│                                                             │
│ SCRIPT DE ROLLBACK:                                         │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ DROP TABLE IF EXISTS user_preferences;                  ││
│ └─────────────────────────────────────────────────────────┘│
│                                                             │
│ ═══════════════════════════════════════════════════════════ │
│                                                             │
│ CHECKLIST:                                                  │
│ ☐ Script de migração revisado                              │
│ ☐ Script de rollback testado                              │
│ ☐ Executado com sucesso em staging                        │
│ ☐ Impacto de performance avaliado                         │
│ ☐ Sem bloqueios de tabela em tabelas grandes             │
│ ☐ Janela de implantação agendada                          │
│ ☐ Monitoramento em vigor                                  │
└─────────────────────────────────────────────────────────────┘

Avaliação de Risco

NÍVEIS DE RISCO DE MIGRAÇÃO:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ RISCO BAIXO (luz verde):                                   │
│ • Adicionando nova tabela                                  │
│ • Adicionando coluna nullable                              │
│ • Adicionando índice (se tabela pequena)                   │
│ → Pode executar a qualquer momento                         │
│                                                             │
│ RISCO MÉDIO (cuidado):                                      │
│ • Adicionando índice a tabela grande                       │
│ • Modificando tipo de coluna (compatível)                  │
│ • Adicionando NOT NULL com padrão                          │
│ → Execute durante baixo tráfego                           │
│ → Monitore performance                                     │
│                                                             │
│ RISCO ALTO (cautela extra):                                 │
│ • Modificando tipo de coluna (incompatível)                │
│ • Removendo coluna                                          │
│ • Removendo tabela                                          │
│ • Grandes migrações de dados                               │
│ → Janela de manutenção necessária                          │
│ ☐ Equipe em standby para problemas                         │
│ ☐ Plano detalhado de rollback                              │
│                                                             │
│ RISCO CRÍTICO (preparação completa):                       │
│ • Mudanças de esquema em tabelas enormes (100M+ linhas)   │
│ • Mudanças de chave estrangeira                            │
│ • Modificações de chave primária                           │
│ → Janela de manutenção estendida                           │
│ → Backup completo antes                                    │
│ → Aprovação executiva                                      │
│ → Sala de guerra durante execução                          │
└─────────────────────────────────────────────────────────────┘

Padrões de Migração Segura

Mudanças Compatíveis com Versões Anteriores

PADRÕES DE MIGRAÇÃO SEGURA:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ PADRÃO 1: EXPANDIR-CONTRAIR                                  │
│                                                             │
│ OBJETIVO: Renomear coluna "name" para "full_name"          │
│                                                             │
│ ❌ ARRISCADO (uma etapa):                                   │
│ ALTER TABLE users RENAME name TO full_name;                │
│ → Quebra código antigo imediatamente                       │
│                                                             │
│ ✅ SEGURO (expandir-contrair):                              │
│                                                             │
│ Etapa 1 (Expandir): Adicionar nova coluna                  │
│ ALTER TABLE users ADD COLUMN full_name VARCHAR(255);       │
│                                                             │
│ Etapa 2: Dual-write no código                              │
│ Escrever em ambos name e full_name                         │
│                                                             │
│ Etapa 3: Backfill de dados                                  │
│ UPDATE users SET full_name = name WHERE full_name IS NULL; │
│                                                             │
│ Etapa 4: Alternar leituras                                  │
│ Ler de full_name                                           │
│                                                             │
│ Etapa 5 (Contrair): Remover coluna antiga (release posterior)│
│ ALTER TABLE users DROP COLUMN name;                        │
│                                                             │
│ Cada etapa é reversível e não-quebrável                    │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Adicionando Colunas NOT NULL

ADIÇÃO SEGURA DE COLUNA NOT NULL:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ OBJETIVO: Adicionar coluna obrigatória "status" aos usuários│
│                                                             │
│ ❌ ARRISCADO:                                               │
│ ALTER TABLE users ADD COLUMN status VARCHAR(20) NOT NULL;  │
│ → Falha se tabela tem linhas existentes                    │
│                                                             │
│ ✅ ABORDAGEM SEGURA:                                        │
│                                                             │
│ Etapa 1: Adicionar coluna nullable com padrão              │
│ ALTER TABLE users ADD COLUMN status VARCHAR(20)            │
│   DEFAULT 'active';                                        │
│                                                             │
│ Etapa 2: Backfill de linhas existentes (em lotes)          │
│ UPDATE users SET status = 'active'                         │
│   WHERE status IS NULL                                     │
│   AND id BETWEEN 1 AND 10000;                             │
│                                                             │
│ Etapa 3: Adicionar restrição NOT NULL                      │
│ ALTER TABLE users ALTER COLUMN status SET NOT NULL;        │
│                                                             │
│ Etapa 4: Opcional - remover padrão                         │
│ ALTER TABLE users ALTER COLUMN status DROP DEFAULT;        │
│                                                             │
│ POR QUE LOTES:                                              │
│ UPDATE grande bloqueia tabela                              │
│ Lotes de 10k-50k linhas minimizam tempo de bloqueio       │
│ Execute durante períodos de baixo tráfego                  │
└─────────────────────────────────────────────────────────────┘

Migrações de Tabelas Grandes

Operações em Lotes

LIDANDO COM TABELAS GRANDES:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ PROBLEMA:                                                   │
│ Tabela: events (500M linhas)                               │
│ Necessário: Atualizar formato da coluna event_data         │
│                                                             │
│ ❌ RUIM: Um UPDATE gigante                                 │
│ UPDATE events SET event_data = transform(event_data);     │
│ → Bloqueia tabela por horas                               │
│ → Log de transação explode                                │
│ → Aplicação dá timeout                                     │
│                                                             │
│ ✅ BOM: Updates em lotes                                   │
│                                                             │
│ ABORDAGEM:                                                  │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ -- Executar em loop, 10k linhas por vez                ││
│ │ UPDATE events                                           ││
│ │ SET event_data = transform(event_data)                 ││
│ │ WHERE id IN (                                           ││
│ │   SELECT id FROM events                                ││
│ │   WHERE needs_migration = true                         ││
│ │   LIMIT 10000                                          ││
│ │ );                                                      ││
│ │                                                         ││
│ │ -- Dormir entre lotes                                  ││
│ │ SELECT pg_sleep(0.5);                                  ││
│ └─────────────────────────────────────────────────────────┘│
│                                                             │
│ MONITORAMENTO:                                              │
│ • Linhas processadas: 150,000 / 500,000,000                │
│ • Tempo estimado: 8 horas                                  │
│ • Carga do banco: Normal                                   │
│ • Erros: 0                                                 │
│                                                             │
│ EXECUTAR COMO: Job em background, não implantação          │
└─────────────────────────────────────────────────────────────┘

Criação de Índice com Zero Tempo de Inatividade

CRIANDO ÍNDICES COM SEGURANÇA:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ PROBLEMA:                                                   │
│ Necessário índice em tabela grande (100M linhas)          │
│ CREATE INDEX bloqueia tabela durante criação               │
│                                                             │
│ ❌ RUIM:                                                    │
│ CREATE INDEX idx_users_email ON users(email);              │
│ → Bloqueia tabela por minutos a horas                      │
│                                                             │
│ ✅ BOM (PostgreSQL):                                        │
│ CREATE INDEX CONCURRENTLY idx_users_email ON users(email); │
│ → Constrói em background                                  │
│ → Sem bloqueio na tabela                                  │
│ → Ligeiramente mais lento, mas seguro                     │
│                                                             │
│ ✅ BOM (MySQL 5.6+):                                        │
│ ALTER TABLE users ADD INDEX idx_email(email),              │
│   ALGORITHM=INPLACE, LOCK=NONE;                           │
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ CUIDADOS:                                                   │
│                                                             │
│ • CONCURRENTLY não funciona em transações                 │
│ • Se falhar, índice é inválido - deve ser removido        │
│ • Monitore espaço em disco (constrói índice ao lado)      │
│ • Pode levar mais tempo que CREATE INDEX regular          │
│                                                             │
│ TAREFA GITSCRUM:                                           │
│ Labels: database, low-risk                                 │
│ Nota: Usando CONCURRENTLY, nenhum tempo de inatividade esperado│
└─────────────────────────────────────────────────────────────┘

Planejamento de Rollback

Toda Migração Precisa de Rollback

REQUISITOS DE ROLLBACK:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ REGRA: NENHUMA MIGRAÇÃO SEM ROLLBACK                       │
│                                                             │
│ ESTRUTURA DE ARQUIVO DE MIGRAÇÃO:                           │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ migrations/                                             ││
│ │ └── 2024_01_15_120000_add_preferences_table.sql        ││
│ │     ├── up.sql     (migração para frente)              ││
│ │     └── down.sql   (rollback)                          ││
│ └─────────────────────────────────────────────────────────┘│
│                                                             │
│ EXEMPLO:                                                    │
│                                                             │
│ up.sql:                                                    │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ CREATE TABLE user_preferences (...);                    ││
│ │ CREATE INDEX idx_prefs_user ON user_preferences(...);  ││
│ └─────────────────────────────────────────────────────────┘│
│                                                             │
│ down.sql:                                                  │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ DROP INDEX IF EXISTS idx_prefs_user;                   ││
│ │ DROP TABLE IF EXISTS user_preferences;                 ││
│ └─────────────────────────────────────────────────────────┘│
│                                                             │
│ TESTANDO ROLLBACK:                                          │
│ 1. Executar migração                                       │
│ 2. Verificar sucesso                                        │
│ 3. Executar rollback                                        │
│ 4. Verificar estado limpo                                   │
│ 5. Executar migração novamente                              │
│ 6. Deve funcionar limpo                                     │
│                                                             │
│ Se rollback for impossível (perda de dados), documente     │
└─────────────────────────────────────────────────────────────┘

Coordenação de Implantação

Fluxo de Implantação de Migração

PROCESSO DE IMPLANTAÇÃO DE MIGRAÇÃO:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ PRÉ-IMPLANTAÇÃO:                                            │
│                                                             │
│ ☐ Migração testada em staging                              │
│ ☐ Rollback testado em staging                              │
│ ☐ Impacto de performance medido                            │
│ ☐ Janela de implantação agendada                           │
│ ☐ Equipe notificada                                        │
│ ☐ Backup confirmado                                        │
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ ORDEM DE IMPLANTAÇÃO:                                       │
│                                                             │
│ 1. BACKUP                                                   │
│    Snapshot do banco antes da migração                     │
│                                                             │
│ 2. MIGRAR                                                   │
│    Executar migração em produção                           │
│                                                             │
│ 3. VERIFICAR                                                │
│    Confirmar migração bem-sucedida                         │
│    Verificar estrutura da tabela                            │
│    Verificar dados se aplicável                            │
│                                                             │
│ 4. IMPLANTAR CÓDIGO                                         │
│    Implantar aplicação que usa novo esquema                │
│                                                             │
│ 5. MONITORAR                                                │
│    Observar por erros                                      │
│    Verificar performance de queries                        │
│    Verificar comportamento da aplicação                    │
│                                                             │
│ 6. MARCAR CONCLUÍDO                                         │
│    Atualizar tarefa GitScrum                               │
│    Documentar quaisquer problemas                          │
│                                                             │
│ SE PROBLEMAS:                                               │
│ → Fazer rollback da aplicação                              │
│ → Fazer rollback da migração                               │
│ → Investigar em staging                                    │
└─────────────────────────────────────────────────────────────┘

Soluções Relacionadas