Pergunta

Quais são os melhores métodos para rastrear e/ou automatizar alterações no esquema do banco de dados?Nossa equipe usa Subversion para controle de versão e conseguimos automatizar algumas de nossas tarefas dessa maneira (enviar compilações para um servidor de teste, implantar código testado em um servidor de produção), mas ainda estamos fazendo atualizações de banco de dados manualmente.Eu gostaria de encontrar ou criar uma solução que nos permita trabalhar de forma eficiente em servidores com ambientes diferentes, enquanto continuamos a usar o Subversion como um back-end através do qual as atualizações de código e banco de dados são enviadas para vários servidores.

Muitos pacotes de software populares incluem scripts de atualização automática que detectam a versão do banco de dados e aplicam as alterações necessárias.Esta é a melhor maneira de fazer isso mesmo em uma escala maior (em vários projetos e, às vezes, em vários ambientes e idiomas)?Em caso afirmativo, existe algum código que simplifique o processo ou é melhor apenas implementar nossa própria solução?Alguém já implementou algo semelhante antes e integrou-o aos ganchos pós-commit do Subversion, ou isso é uma má ideia?

Embora uma solução que suporte múltiplas plataformas seja preferível, definitivamente precisamos oferecer suporte à pilha Linux/Apache/MySQL/PHP, já que a maior parte do nosso trabalho é nessa plataforma.

Foi útil?

Solução

No mundo Rails, existe o conceito de migrações, scripts nos quais as alterações no banco de dados são feitas em Ruby, em vez de um tipo de SQL específico do banco de dados.Seu código de migração Ruby acaba sendo convertido no DDL específico do seu banco de dados atual;isso torna a troca de plataformas de banco de dados muito fácil.

Para cada alteração feita no banco de dados, você escreve uma nova migração.As migrações normalmente têm dois métodos:um método "up" no qual as alterações são aplicadas e um método "down" no qual as alterações são desfeitas.Um único comando atualiza o banco de dados e também pode ser usado para trazer o banco de dados para uma versão específica do esquema.No Rails, as migrações são mantidas em seu próprio diretório no diretório do projeto e são verificadas no controle de versão como qualquer outro código de projeto.

Este guia Oracle para migrações Rails cobre muito bem as migrações.

Os desenvolvedores que usam outras linguagens analisaram as migrações e implementaram suas próprias versões específicas de linguagem.eu sei de Ruckusing, um sistema de migrações PHP modelado a partir das migrações do Rails;pode ser o que você está procurando.

Outras dicas

Usamos algo semelhante ao bcwoord para manter nossos esquemas de banco de dados sincronizados em 5 instalações diferentes (produção, teste e algumas instalações de desenvolvimento) e com backup no controle de versão, e funciona muito bem.Vou elaborar um pouco:


Para sincronizar a estrutura do banco de dados, temos um único script, update.php, e vários arquivos numerados 1.sql, 2.sql, 3.sql, etc.O script usa uma tabela extra para armazenar o número da versão atual do banco de dados.Os arquivos N.sql são elaborados manualmente, para passar da versão (N-1) para a versão N do banco de dados.

Eles podem ser usados ​​para adicionar tabelas, adicionar colunas, migrar dados de um formato de coluna antigo para um novo e, em seguida, eliminar a coluna, inserir linhas de dados "mestres", como tipos de usuário, etc.Basicamente, ele pode fazer qualquer coisa e, com scripts de migração de dados adequados, você nunca perderá dados.

O script de atualização funciona assim:

  • Conecte-se ao banco de dados.
  • Faça um backup do banco de dados atual (porque as coisas vai dar errado) [mysqldump].
  • Crie uma tabela de contabilidade (chamada _meta) se ela não existir.
  • Leia a VERSÃO atual da tabela _meta.Assuma 0 se não for encontrado.
  • Para todos os arquivos .sql numerados acima de VERSION, execute-os em ordem
  • Se um dos arquivos produziu um erro:reverter para o backup
  • Caso contrário, atualize a versão na tabela de escrituração contábil para o arquivo .sql mais alto executado.

Tudo vai para o controle de origem, e cada instalação possui um script para atualizar para a versão mais recente com uma única execução de script (chamando update.php com a senha de banco de dados adequada, etc.).Atualizamos o SVN nos ambientes de teste e produção por meio de um script que chama automaticamente o script de atualização do banco de dados, portanto, uma atualização de código vem com as atualizações de banco de dados necessárias.

Também podemos usar o mesmo script para recriar todo o banco de dados do zero;apenas eliminamos e recriamos o banco de dados e, em seguida, executamos o script que irá preencher novamente o banco de dados.Também podemos usar o script para preencher um banco de dados vazio para testes automatizados.


Demorou apenas algumas horas para configurar este sistema, é conceitualmente simples e todos recebem o esquema de numeração de versão, e tem sido inestimável para poder avançar e evoluir o design do banco de dados, sem ter que se comunicar ou executar manualmente as modificações em todos os bancos de dados.

Cuidado ao colar consultas do phpMyAdmin! Essas consultas geradas geralmente incluem o nome do banco de dados, o que você definitivamente não quer, pois isso quebrará seus scripts!Algo como CRIAR TABELA mydb.newtable(...) falhará se o banco de dados no sistema não for chamado mydb.Criamos um gancho SVN pré-comentário que não permitirá arquivos .sql contendo o mydb string, que é um sinal claro de que alguém copiou/colou do phpMyAdmin sem a devida verificação.

Minha equipe cria scripts de todas as alterações do banco de dados e envia esses scripts para o SVN, junto com cada versão do aplicativo.Isso permite alterações incrementais no banco de dados, sem perder nenhum dado.

Para passar de uma versão para a próxima, você só precisa executar o conjunto de scripts de mudança e seu banco de dados estará atualizado e você ainda terá todos os seus dados.Pode não ser o método mais fácil, mas definitivamente é eficaz.

O problema aqui é realmente tornar mais fácil para os desenvolvedores criarem scripts de suas próprias alterações locais no controle de origem para compartilhar com a equipe.Enfrentei esse problema há muitos anos e me inspirei na funcionalidade do Visual Studio para profissionais de banco de dados.Se você deseja uma ferramenta de código aberto com os mesmos recursos, tente isto: http://dbsourcetools.codeplex.com/ Divirta -se, - Nathan.

Se você ainda está procurando soluções:estamos propondo uma ferramenta chamada neXtep designer.É um ambiente de desenvolvimento de banco de dados com o qual você pode colocar todo o seu banco de dados sob controle de versão.Você trabalha em um repositório controlado por versão onde todas as alterações podem ser rastreadas.

Quando precisar lançar uma atualização, você pode confirmar seus componentes e o produto gerará automaticamente o script de atualização SQL da versão anterior.Claro, você pode gerar esse SQL a partir de 2 versões.

Então você tem muitas opções:você pode pegar esses scripts e colocá-los em seu SVN com o código do seu aplicativo para que ele seja implantado pelo seu mecanismo existente.Outra opção é usar o mecanismo de entrega do neXtep:os scripts são exportados em algo chamado "pacote de entrega" (scripts SQL + descritor XML), e um instalador pode entender esse pacote e implantá-lo em um servidor de destino, garantindo consistência estrutural, verificação de dependência, registro da versão instalada, etc.

O produto é GPL e é baseado em Eclipse, portanto roda em Linux, Mac e Windows.Ele também oferece suporte a Oracle, Mysql e Postgresql no momento (o suporte ao DB2 está a caminho).Dê uma olhada no wiki onde você encontrará informações mais detalhadas:http://www.nextep-softwares.com/wiki

Despeje seu esquema em um arquivo e adicione-o ao controle de origem.Então, uma simples diferença mostrará o que mudou.

Scott Ambler produz uma grande série de artigos (e é coautor de um livro) sobre refatoração de banco de dados, com a ideia de que você deve essencialmente aplicar princípios e práticas de TDD para manter seu esquema.Você configura uma série de testes de unidade de dados iniciais e de estrutura para o banco de dados.Então, antes de alterar qualquer coisa, você modifica/escreve testes para refletir essa alteração.

Já fazemos isso há algum tempo e parece funcionar.Escrevemos código para gerar verificações básicas de nome de coluna e tipo de dados em um conjunto de testes de unidade.Podemos executar novamente esses testes a qualquer momento para verificar se o banco de dados no checkout do SVN corresponde ao banco de dados ativo que o aplicativo está realmente executando.

Acontece que os desenvolvedores às vezes também ajustam seu banco de dados sandbox e negligenciam a atualização do arquivo de esquema no SVN.O código então depende de uma alteração no banco de dados que não foi verificada.Esse tipo de bug pode ser irritantemente difícil de identificar, mas o conjunto de testes irá detectá-lo imediatamente.Isso é particularmente bom se você o incorporar a um plano maior de integração contínua.

K.Scott Allen tem um ou dois artigos decentes sobre controle de versão de esquema, que usa o conceito de scripts/migrações de atualização incremental mencionado em outras respostas aqui;ver http://odetocode.com/Blogs/scott/archive/2008/01/31/11710.aspx.

É um pouco de baixa tecnologia e pode haver uma solução melhor por aí, mas você pode simplesmente armazenar seu esquema em um script SQL que pode ser executado para criar o banco de dados.Acho que você pode executar um comando para gerar esse script, mas infelizmente não conheço o comando.

Em seguida, envie o script para o controle de origem junto com o código que funciona nele.Quando você precisar alterar o esquema junto com o código, o check-in do script poderá ser feito junto com o código que requer o esquema alterado.Então, as diferenças no script indicarão as diferenças nas alterações do esquema.

Com este script, você poderia integrá-lo ao DBUnit ou algum tipo de script de construção, então parece que ele poderia se encaixar nos seus processos já automatizados.

Se você estiver usando C#, dê uma olhada no Subsonic, uma ferramenta ORM muito útil, mas que também gera script sql para recriar seu esquema e/ou dados.Esses scripts podem então ser colocados no controle de origem.

http://subsonicproject.com/

Usei a seguinte estrutura de projeto de banco de dados no Visual Studio para vários projetos e funcionou muito bem:

Base de dados

Alterar scripts

0.PreDeploy.sql

1.SchemaChanges.sql

2.DataChanges.sql

3.Permissões.sql

Criar scripts

Sprocs

Funções

Visualizações

Nosso sistema de compilação atualiza o banco de dados de uma versão para outra executando os scripts na seguinte ordem:

1.PreDeploy.sql

2.SchemaChanges.sql

Conteúdo da pasta Criar Scripts

2.DataChanges.sql

3.Permissões.sql

Cada desenvolvedor verifica suas alterações em busca de um bug/recurso específico anexando seu código no final de cada arquivo.Depois que uma versão principal for concluída e ramificada no controle de origem, o conteúdo dos arquivos .sql na pasta Alterar Scripts será excluído.

Usamos uma solução muito simples, mas eficaz.

Para novas instalações, temos um arquivo metadata.sql no repositório que contém todo o esquema do banco de dados, então no processo de construção usamos este arquivo para gerar o banco de dados.

Para atualizações, adicionamos as atualizações no software codificado.Nós o mantemos codificado porque não gostamos de resolver problemas antes que eles realmente sejam um problema, e esse tipo de coisa não provou ser um problema até agora.

Então em nosso software temos algo assim:

RegisterUpgrade(1, 'ALTER TABLE XX ADD XY CHAR(1) NOT NULL;');

Este código irá verificar se o banco de dados está na versão 1 (que fica armazenado em uma tabela criada automaticamente), se estiver desatualizado, então o comando é executado.

Para atualizar o metadata.sql no repositório, executamos essas atualizações localmente e, em seguida, extraímos os metadados completos do banco de dados.

A única coisa que acontece de vez em quando é esquecer de confirmar o metadata.sql, mas isso não é um grande problema porque é fácil de testar no processo de construção e também a única coisa que pode acontecer é fazer uma nova instalação com um banco de dados desatualizado e o atualizou no primeiro uso.

Além disso, não oferecemos suporte a downgrades, mas isso ocorre intencionalmente. Se algo falhar em uma atualização, restauramos a versão anterior e corrigimos a atualização antes de tentar novamente.

Eu crio pastas com nomes de versões de compilação e coloco scripts de atualização e downgrade nelas.Por exemplo, você poderia ter as seguintes pastas:1.0.0, 1.0.1 e 1.0.2.Cada um contém o script que permite atualizar ou fazer downgrade de seu banco de dados entre versões.

Se um cliente ou cliente ligar para você com um problema com a versão 1.0.1 e você estiver usando a 1.0.2, trazer o banco de dados de volta para a versão dele não será um problema.

No seu banco de dados, crie uma tabela chamada “schema” onde você coloca a versão atual do banco de dados.Então é fácil escrever um programa que possa atualizar ou fazer downgrade de seu banco de dados.

Assim como Joey disse, se você estiver no mundo Rails, use Migrations.:)

Para meu projeto PHP atual usamos a ideia de migrações Rails e temos um diretório de migrações no qual mantemos os arquivos com o título "migration_XX.sql" onde XX é o número da migração.Atualmente esses arquivos são criados manualmente à medida que as atualizações são feitas, mas sua criação pode ser facilmente modificada.

Depois temos um script chamado "Migration_watcher" que, como estamos no pré-alfa, atualmente é executado a cada carregamento de página e verifica se há um novo arquivo migração_XX.sql onde XX é maior que a versão de migração atual.Nesse caso, ele executa todos os arquivos migração_XX.sql até o maior número no banco de dados e pronto!as alterações de esquema são automatizadas.

Se você precisar reverter o sistema, serão necessários muitos ajustes, mas é simples e tem funcionado muito bem para nossa pequena equipe até agora.

Eu recomendaria usar Ant (plataforma cruzada) para o lado de "script" (já que ele pode praticamente se comunicar com qualquer banco de dados via jdbc) e Subversion para o repositório de origem.O Ant permitirá que você "faça backup" do seu banco de dados em arquivos locais, antes de fazer alterações.1.Backup do esquema de banco de dados existente para arquivar via Ant 2.Controle de versão para repositório de subversão via Ant 3.enviar novas instruções sql para db via Ant

O Toad for MySQL possui uma função chamada comparação de esquema que permite sincronizar 2 bancos de dados.É a melhor ferramenta que usei até agora.

As migrações IMHO têm um grande problema:

Atualizar de uma versão para outra funciona bem, mas fazer uma nova instalação de uma determinada versão pode levar uma eternidade se você tiver centenas de tabelas e um longo histórico de alterações (como nós).

A execução de todo o histórico de deltas desde a linha de base até a versão atual (para bancos de dados de centenas de clientes) pode levar muito tempo.

Eu gosto do jeito que Ei lida com migrações de banco de dados.Uma migração é basicamente um script PHP implementando CDbMigration. CDbMigration define um up método que contém a lógica de migração.Também é possível implementar um down método para apoiar a reversão da migração.Alternativamente, safeUp ou safeDown pode ser usado para garantir que a migração seja feita no contexto de uma transação.

Ferramenta de linha de comando do Yii yiic contém suporte para criar e executar migrações.As migrações podem ser aplicadas ou revertidas, uma por uma ou em lote.A criação de uma migração resulta em código para uma implementação de classe PHP CDbMigration, nomeado exclusivamente com base em um carimbo de data/hora e um nome de migração especificado pelo usuário.Todas as migrações aplicadas anteriormente ao banco de dados são armazenadas em uma tabela de migração.

Para mais informações consulte o Migração de banco de dados artigo do manual.

Experimente db-deploy - principalmente uma ferramenta Java, mas também funciona com php.

Existe uma linha de comando mysql-diff ferramenta que compara esquemas de banco de dados, onde o esquema pode ser um banco de dados ativo ou script SQL em disco.É bom para a maioria das tarefas de migração de esquema.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top