DataARTIGO

Aplicando controle de versão em banco de dados

Um tempo atrás eu escrevi sobre estratégias para colocar artefatos de banco de dados sob controle de origem. Na época, pensei que uma abordagem de sincronização de esquema (implementado pelo projeto Visual Studio Database) era o caminho a percorrer. Entre outras coisas, parecia mais amigável.

Bem, nós tentamos com o bom e velho projeto VS Database da faculdade. Usamos isso para criar um banco de dados local para desenvolvimento e testes automatizados e para gerar scripts de deployment.

Os resultados não foram ótimos. Enquanto pudemos fazê-lo funcionar para as necessidades de desenvolvimento/testes, criando automaticamente uma versão local do nosso banco de dados, scripts para implantações de deployment provaram ser algo muito distante. Conseguir um script de deploy confiável acabou sendo muito difícil.

O resultado final foi que migramos para um esquema de abordagem de migrações (perdoem o trocadilho).

Tudo ou nada

O problema básico com o projeto VS Database é que ele exige perfeição para que possa ser verdadeiramente útil. Permita que eu explique.

Nós temos um número bastante grande de bancos de dados interdependentes. Destes, apenas um punhado é diretamente relevante para a nossa aplicação e realmente muda durante o desenvolvimento. Portanto, é perfeitamente suficiente para obter apenas os bancos de dados sob controle de versão. O resto deles seria bom, claro, mas não seria absolutamente necessário.

No entanto, o Visual Studio requer que todos eles estejam sob controle de versão ou algo assim. Toda vez que você criar, ele tenta recriar e validar o esquema de banco de dados. Qualquer referência a outro banco de dados que ele não conhece faz com que a construção falhe. Assim, a fim de fazer o build, você tem que desistir dessas referências ou colocar outros bancos de dados sob o controle de versão do Visual Studio.

Em teoria, essa exigência deve ser tratada colocando todos os seus bancos de dados sob controle de versão. Na prática, isso não é prático (mais uma vez, perdoem o trocadilho). Demora muito tempo, é doloroso etc. E, assim, você pega atalhos.

Ele desencadeou um problema

Com triggers, seguimos um atalho que gerou maus resultados.

O nosso banco de dados tem triggers que escrevem operações CRUD em tabelas específicas para um banco de dados diferente. Entre outras coisas, isso significa que uma atualização para 1 registro em tal tabela resulta em mais de uma atualização no banco de dados.

Infelizmente, o NHibernate (nosso ORM) não gosta disso. Ele espera que um número específico de registros seja atualizado. Se ele vê mais (ou menos) do que isso, ele enlouquece e lança um erro “Unexpected row count”.

Felizmente, há uma solução simples para isso: basta modificar o trigger para não retornar contagens de linhas atualizadas. Tudo que você precisa é que esse trigger esteja sob controle de versão. Simples, não?

Bem, colocar um trigger que faz referência a outro banco de dados no controle de origem nos obrigou a colocar esse outro banco de dados sob controle de origem também. O que leva tempo e energia. Tempo e energia que poderiam ser usados em outro lugar.

Nós não conhecíamos sobre o problema do NHibernate quando colocamos originalmente o banco de dados sob controle de origem. Na época, largando esses triggers do controle de origem não parecia uma má ideia. A troca era justificável.

E assim o fizemos. Nosso banco de dados compilado e nosso aplicativo funcionaram muito bem. O desenvolvimento continuou alheio a essa questão até bem tarde no ciclo de teste.

Agora, eu percebo que isso não teria acontecido se tivéssemos feito as coisas do “jeito certo” em vez de pegar atalhos. E enquanto isso pode muito bem ser verdade, quando chegamos ao triggers, já tínhamos lutado por um bom tempo, pelo menos com as bases de dados principais sob controle de versão. Gastar ainda mais tempo em bancos de dados do quais sequer precisamos não era uma proposta atraente.

O que me traz de volta ao meu ponto original. Se a ferramenta que você usa torna o processo muito oneroso, então talvez não seja a ferramenta certa.

Nesse sentido, as migrações de banco de dados são muito mais generosas. Contanto que você possa gerar um esquema base que irá compilar no banco de dados, nada mais importa. Suas referências não têm que realmente existir etc.

Novamente, isso não significa uma solução perfeita e, provavelmente, não expõe certos tipos de problemas automaticamente. No entanto, pelo menos você pode seguir em frente. E assim nós fizemos.

?

Texto original disponível em http://tatiyants.com/database-source-control-revisited/

Gosta de escrever coisas engraças sobre tecnologia. É criador do JS.js e do movimento MoreSQL, além de inventor do Guilt Driven Development.

Ver perfil