Alembic: Versionamento de Banco de Dados (Parte 2)
Source: Dev.to
Na Parte 1 deste artigo, aprendemos os fundamentos do Alembic, como inicializar o ambiente de migração e criar migrações manuais. Agora vamos elevar o nível: automatizar o processo e lidar com bancos de dados já populados.
Automatizando Migrações com --autogenerate
Configurando o target_metadata
Para que a autogeração funcione, o Alembic precisa do objeto MetaData que contém suas definições de modelo. Edite migrations/env.py:
# migrations/env.py
# Importe o seu objeto Base ou os seus modelos
from my_app.models import Base
# ...
# Defina o target_metadata
target_metadata = Base.metadata
# ...
Dica: Certifique‑se de que todos os modelos foram importados antes de definir target_metadata, caso contrário o Alembic não os detectará.
Gerando a Migração Automática
Com target_metadata configurado, crie uma nova revisão usando a flag --autogenerate:
alembic revision --autogenerate -m "add_profile_column_to_users"
O Alembic comparará o estado atual do banco com os modelos e gerará as funções upgrade() e downgrade() (ex.: op.add_column, op.create_table).
Atenção: revise sempre o script gerado; mudanças complexas, como renomear colunas, podem exigir ajustes manuais1.
Começando com um Banco de Dados Existente
Quando o projeto já possui um banco populado, executar alembic upgrade head tentaria recriar tabelas existentes, gerando erro. Use o processo de Baselining2.
Passo 1 – Criar a Migração de “Estado Zero”
Gere uma migração que represente o estado atual do banco:
alembic revision --autogenerate -m "baseline_initial_state"
Se os modelos estiverem sincronizados com o banco, o script será quase vazio; caso contrário, conterá os comandos necessários para criar as tabelas existentes.
Passo 2 – O Comando stamp
Em vez de aplicar a migração (que falharia), informe ao Alembic que o banco já está naquela versão:
alembic stamp head
stamp cria a tabela alembic_version e insere o ID da revisão mais recente (head) sem executar nenhum código de migração. A partir daí, novas migrações podem ser criadas normalmente.
Melhores Práticas e Arquitetura
| Prática | Descrição |
|---|---|
| Scripts Atômicos | Cada migração deve focar em uma única alteração lógica (ex.: adicionar uma tabela ou um conjunto de colunas relacionadas). |
| Teste de Downgrade | Sempre teste o comando downgrade para garantir que você pode reverter alterações sem ficar “preso” em uma versão quebrada. |
| Integração no CI/CD | Automatize alembic upgrade head no pipeline de deploy para manter o banco sincronizado com o código. |
| Cuidado com Dados | Migrações DDL alteram estrutura. Para transformar dados (ex.: string → JSON), use op.execute() dentro do script de migração. |
Conclusão
O Alembic transforma o gerenciamento de banco de dados de uma tarefa manual e arriscada em um processo versionado e automatizado. Seja iniciando um projeto do zero ou organizando um legado, ele é indispensável para desenvolvedores Python que buscam agilidade e segurança na arquitetura de dados.