Mecanismos para rastrear alterações no esquema do banco de dados [fechado]

135

Quais são os melhores métodos para rastrear e / ou automatizar alterações no esquema do banco de dados? Nossa equipe usa o Subversion para controle de versão e conseguimos automatizar algumas de nossas tarefas dessa maneira (forçando a compilação para um servidor intermediário, implantando o código testado em um servidor de produção), mas ainda estamos fazendo atualizações manualmente do banco de dados. Gostaria de encontrar ou criar uma solução que nos permita trabalhar eficientemente em servidores com ambientes diferentes, continuando 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. Essa é 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 existente que simplifique o processo ou é melhor lançar nossa própria solução? Alguém implementou algo semelhante antes e o integrou aos ganchos de submissão do Subversion, ou é uma má idéia?

Embora uma solução que suporte várias plataformas seja preferível, definitivamente precisamos oferecer suporte à pilha Linux / Apache / MySQL / PHP, pois a maioria do nosso trabalho está nessa plataforma.

pix0r
fonte

Respostas:

56

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

Para cada alteração feita no banco de dados, você escreve uma nova migração. As migrações geralmente têm dois métodos: um método "ativo" no qual as alterações são aplicadas e um método "ativo" 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 da Oracle para migrações do Rails cobre muito bem as migrações.

Os desenvolvedores que usam outros idiomas analisaram as migrações e implementaram suas próprias versões específicas do idioma. Conheço o Ruckusing , um sistema de migrações PHP modelado após as migrações do Rails; pode ser o que você está procurando.

Joey deVilla
fonte
1
Ruckusing FTW - nós o adaptamos ao nosso sistema db e estamos muito felizes com ele.
Piskvor saiu do prédio
Agora ele está localizado no github: github.com/ruckus/ruckusing-migrations
50

Usamos algo semelhante ao bcwoord para manter nossos esquemas de banco de dados sincronizados em 5 instalações diferentes (produção, preparo 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 arquivo. base de dados. Os arquivos N.sql são criados 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 antigo para um novo formato de coluna e soltar a coluna, inserir linhas de dados "principais", como tipos de usuários, etc. Basicamente, ele pode fazer qualquer coisa e com os dados adequados. scripts de migração, 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 vão 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 gerou um erro: reverta para o backup
  • Caso contrário, atualize a versão na tabela de contabilidade para o arquivo .sql mais alto executado.

Tudo entra no controle de origem, e toda 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 apropriada do banco de dados, etc.). Atualizamos os 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 é fornecida com as atualizações necessárias.

Também podemos usar o mesmo script para recriar todo o banco de dados do zero; nós simplesmente descartamos e recriamos o banco de dados e, em seguida, executamos o script que repovoará completamente 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 todo mundo recebe o esquema de numeração de versões, e foi inestimável ter a capacidade de 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, que você definitivamente não deseja, pois isso interromperá seus scripts! Algo como CREATE TABLE mydb. newtable(...) falhará se o banco de dados no sistema não for chamado mydb. Criamos um gancho SVN de pré-comentário que não permitirá que arquivos .sql contenham a mydbstring, o que é um sinal claro de que alguém copiou / colou do phpMyAdmin sem a verificação adequada.

rix0rrr
fonte
Como você lidou com colisões? Vários desenvolvedores alterando o mesmo elemento no banco de dados, por exemplo, um procedimento armazenado? Isso pode acontecer se você estiver trabalhando no mesmo ramo na mesma ramificação, ou se tiver duas linhas de desenvolvimento em andamento (duas ramificações)
Asaf Mesika
Colisões eram muito raras; a única coisa que aconteceu realmente é que duas pessoas tentariam criar o mesmo arquivo N.sql. Obviamente, o primeiro vence e o segundo é forçado a renomear para o próximo número mais alto e tentar novamente. Não tínhamos o controle de versão do banco de dados em uma ramificação.
rix0rrr
12

Minha equipe executa scripts de todas as alterações no banco de dados e confirma esses scripts no SVN, juntamente com cada versão do aplicativo. Isso permite alterações incrementais do banco de dados, sem perda de dados.

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

Brandon Wood
fonte
1
como você define todas as alterações?
23717 Smith
10

O problema aqui está realmente facilitando aos desenvolvedores o script de suas próprias alterações locais no controle de origem para compartilhar com a equipe. Eu enfrentei esse problema por muitos anos e fui inspirado pela funcionalidade do Visual Studio para profissionais de banco de dados. Se você deseja uma ferramenta de código aberto com os mesmos recursos, tente o seguinte: http://dbsourcetools.codeplex.com/ Divirta-se, - Nathan.


fonte
10

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 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 você precisar liberar uma atualização, poderá confirmar seus componentes e o produto gerará automaticamente o script de atualização SQL da versão anterior. Obviamente, você pode gerar esse SQL a partir de duas versões.

Então você tem muitas opções: você pode pegar esses scripts e colocá-los no seu SVN com o código do aplicativo para que sejam implantados pelo 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 no servidor de destino, garantindo consistência estrutural, dependência verifique, registrando a versão instalada, etc.

O produto é GPL e é baseado no Eclipse, portanto, é executado no Linux, Mac e Windows. Ele também suporta 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

Christophe Fondacci
fonte
Parece interessante. Também possui interface de linha de comando ou está planejada?
Piskvor saiu do prédio 25/10/10
8

Scott Ambler produz uma grande série de artigos (e é co-autor de um livro ) sobre refatoração de banco de dados, com a idéia de que você deve aplicar essencialmente os princípios e práticas de TDD para manter seu esquema. Você configura uma série de testes de estrutura e de unidade de dados iniciais para o banco de dados. Antes de alterar qualquer coisa, modifique / escreva testes para refletir essa alteração.

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 de sandbox e negligenciam a atualização do arquivo de esquema no SVN. O código depende de uma alteração de banco de dados que não foi registrada. Esse tipo de bug pode ser irritantemente difícil de definir, mas a suíte de testes o captará imediatamente. Isso é particularmente interessante se você o incorporar a um plano maior de Integração Contínua.

Sam McAfee
fonte
7

Despejar seu esquema em um arquivo e adicioná-lo ao controle de origem. Então, um simples diff mostrará o que mudou.

programador morto
fonte
1
O dump precisa estar no SQL, como um mysqldump, o dump do Oracle é binário.
Osama Al-Maadeed 20/10/08
7
Há também um problema mais fundamental com a diferença de esquema. Como você diferencia uma gota de coluna + adição de uma renomeação de coluna. A resposta é simples: você não pode. Essa é a razão pela qual você precisa registrar as operações reais de alteração de esquema.
Psp1
O diff mostrará que uma coluna se foi, enquanto a outra apareceu (a menos que tenham o mesmo nome), e na maioria das vezes é o suficiente. Criar scripts para todas as alterações de esquema é um bom caminho, é claro: no Drupal, isso é tratado por um gancho especial, por exemplo.
deadprogrammer
5

É meio 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, confirme o script no controle de origem, juntamente com o código que funciona nele. Quando você precisar alterar o esquema junto com o código, o script pode ser verificado junto com o código que requer o esquema alterado. Em seguida, diffs no script indicará diffs nas alterações do esquema.

Com esse script, você pode integrá-lo ao DBUnit ou a algum tipo de script de construção, para que ele possa se encaixar nos seus processos já automatizados.

Mike Stone
fonte
Sim, é praticamente o que temos no momento. Infelizmente, isso não nos fornece uma maneira fácil de modificar bancos de dados existentes - o script SQL gerado pelo mysqldump assume que você está criando a tabela do zero (ou substituindo uma tabela, se existir). Precisamos de algo um pouco mais de alta tecnologia, porque ele precisa aplicar uma sequência de instruções ALTER TABLE ao banco de dados e, para fazer isso corretamente, precisa estar ciente do estado atual do banco de dados.
pix0r
5

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

http://subsonicproject.com/

Dan
fonte
Parece ser um URL morto até esse momento.
Mark Schultheiss
5

Eu 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.Permissions.sql

Criar scripts

Sprocs

Funções

Visualizações

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

1.PreDeploy.sql

2.SchemaChanges.sql

Conteúdo da pasta Criar Scripts

2.DataChanges.sql

3.Permissions.sql

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

tbreffni
fonte
5

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 e, no processo de compilação, usamos esse arquivo para gerar o banco de dados.

Para atualizações, adicionamos as atualizações no software codificado. Mantemos o código codificado porque não gostamos de resolver problemas antes que realmente seja um problema, e esse tipo de coisa não se mostrou um problema até agora.

Portanto, em nosso software, temos algo parecido com isto:

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

Esse código verificará se o banco de dados está na versão 1 (que é armazenada em uma tabela criada automaticamente), se está desatualizado e o comando é executado.

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

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

Além disso, não oferecemos suporte para downgrades, mas é por design. Se algo ocorrer em uma atualização, restauramos a versão anterior e corrigimos a atualização antes de tentar novamente.

Fabio Gomes
fonte
4

Crio pastas com o nome das versões de compilação e coloco scripts de atualização e downgrade lá. Por exemplo, você pode 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 o downgrade do 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 à sua versão não será um problema.

No seu banco de dados, crie uma tabela chamada "esquema" na qual você coloca a versão atual do banco de dados. Em seguida, é fácil escrever um programa que possa atualizar ou degradar seu banco de dados.

Assim como Joey disse, se você estiver no mundo do Rails, use Migrações. :)

Louis Salin
fonte
3

Para o meu projeto PHP atual, usamos a idéia de migrações de trilhos e temos um diretório de migrações no qual mantemos os arquivos com o título "migration_XX.sql" em que 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.

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

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

Eric Scrivner
fonte
3

Eu recomendaria o uso do Ant (plataforma cruzada) para o lado "script" (já que ele pode praticamente conversar com qualquer banco de dados existente via jdbc) e o 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. faça backup do esquema db existente para arquivar via Ant 2. controle de versão no repositório Subversion via Ant 3. envie novas instruções sql para db via Ant

Cruz
fonte
3

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

Petah
fonte
3

Eu gosto da maneira como o Yii lida com as migrações de banco de dados. Uma migração é basicamente um script PHP implementado CDbMigration. CDbMigrationdefine um upmétodo que contém a lógica de migração. Também é possível implementar um downmétodo para suportar a reversão da migração. Como alternativa, safeUpou safeDownpode ser usado para garantir que a migração seja feita no contexto de uma transação.

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

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

Ton van den Heuvel
fonte
2

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

A atualização 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 centenas de bancos de dados de clientes) pode levar muito tempo.

Edson Medina
fonte
0

Existe uma ferramenta mysql-diff de linha de comando que compara esquemas de banco de dados, em que 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.

stepancheg
fonte