Como você gerencia bancos de dados em desenvolvimento, teste e produção?

StackOverflow https://stackoverflow.com/questions/6371

  •  08-06-2019
  •  | 
  •  

Pergunta

Tive dificuldade em encontrar bons exemplos de como gerenciar esquemas e dados de banco de dados entre servidores de desenvolvimento, teste e produção.

Aqui está nossa configuração.Cada desenvolvedor possui uma máquina virtual executando nosso aplicativo e o banco de dados MySQL.É sua caixa de areia pessoal para fazer o que quiserem.Atualmente, os desenvolvedores farão uma alteração no esquema SQL e despejarão o banco de dados em um arquivo de texto que eles enviarão para o SVN.

Queremos implantar um servidor de desenvolvimento de integração contínua que sempre execute o código confirmado mais recente.Se fizermos isso agora, o banco de dados do SVN será recarregado para cada construção.

Temos um servidor de teste (virtual) que executa "Candidatos de liberação". A implantação no servidor de teste é atualmente um processo muito manual e geralmente me envolve carregando o SQL mais recente do SVN e aprimorando -o.Além disso, os dados no servidor de teste são inconsistentes.Você acaba com todos os dados de teste que o último desenvolvedor a confirmar tinha em seu servidor sandbox.

Onde tudo falha é na implantação na produção.Como não podemos substituir os dados ativos pelos dados de teste, isso envolve a recriação manual de todas as alterações do esquema.Se houve um grande número de alterações de esquema ou scripts de conversão para manipular os dados, isso pode ficar muito complicado.

Se o problema fosse apenas o esquema, seria um problema mais fácil, mas há dados "base" no banco de dados que também são atualizados durante o desenvolvimento, como metadados em tabelas de segurança e permissões.

Esta é a maior barreira que vejo no avanço em direção à integração contínua e à construção em uma etapa.Como você resolver isso?


Uma pergunta complementar:como você rastreia versões de banco de dados para saber quais scripts executar para atualizar uma determinada instância de banco de dados?Uma tabela de versões como a que Lance menciona está abaixo do procedimento padrão?


Obrigado pela referência a Tarantino.Não estou em um ambiente .NET, mas encontrei o Página wiki DataBaseChangeMangement para ser muito útil.Especialmente isso Apresentação em PowerPoint (.ppt)

Vou escrever um script Python que verifica os nomes dos *.sql scripts em um determinado diretório em uma tabela no banco de dados e executa aqueles que não estão lá em ordem com base em um número inteiro que forma a primeira parte do nome do arquivo.Se for uma solução bem simples, como suspeito que será, postarei aqui.


Eu tenho um script funcional para isso.Ele cuida da inicialização do banco de dados, se ele não existir, e da execução de scripts de atualização, conforme necessário.Também existem opções para limpar um banco de dados existente e importar dados de teste de um arquivo.Tem cerca de 200 linhas, então não vou postar (embora possa colocar no pastebin se houver interesse).

Foi útil?

Solução

Existem algumas boas opções.Eu não usaria a estratégia "restaurar um backup".

  1. Crie scripts de todas as alterações de esquema e faça com que seu servidor de CI execute esses scripts no banco de dados.Tenha uma tabela de versões para acompanhar a versão atual do banco de dados e só execute os scripts se forem para uma versão mais recente.

  2. Use uma solução de migração.Essas soluções variam de acordo com o idioma, mas para .NET eu uso o Migrator.NET.Isso permite que você versione seu banco de dados e mova para cima e para baixo entre as versões.Seu esquema é especificado em código C#.

Outras dicas

Seus desenvolvedores precisam escrever scripts de alteração (alteração de esquema e dados) para cada bug/recurso em que trabalham, e não simplesmente despejar todo o banco de dados no controle de origem.Esses scripts atualizarão o banco de dados de produção atual para a nova versão em desenvolvimento.

Seu processo de construção pode restaurar uma cópia do banco de dados de produção em um ambiente apropriado e executar todos os scripts do controle de origem nele, o que atualizará o banco de dados para a versão atual.Fazemos isso diariamente para garantir que todos os scripts sejam executados corretamente.

Dê uma olhada em como Ruby on Rails faz isso.

Primeiro, existem os chamados arquivos de migração, que basicamente transformam o esquema e os dados do banco de dados da versão N para a versão N+1 (ou em caso de downgrade da versão N+1 para N).O banco de dados possui uma tabela que informa a versão atual.

Os bancos de dados de teste são sempre limpos antes dos testes de unidade e preenchidos com dados fixos de arquivos.

O livro Refatorando bancos de dados:Design Evolutivo de Banco de Dados pode lhe dar algumas idéias sobre como gerenciar o banco de dados.Uma versão curta também pode ser lida em http://martinfowler.com/articles/evodb.html

Em um projeto PHP + MySQL, o número de revisão do banco de dados foi armazenado no banco de dados e, quando o programa se conecta ao banco de dados, ele primeiro verifica a revisão.Caso o programa necessite de uma revisão diferente, abrirá uma página para atualização do banco de dados.Cada atualização é especificada em código PHP, que alterará o esquema do banco de dados e migrará todos os dados existentes.

  • Nomeie seus bancos de dados da seguinte forma - db_dev , db_test , db_qa , db_prod (obviamente você nunca deve codificar nomes de banco de dados
  • Assim, você seria capaz de implantar até mesmo tipos diferentes de banco de dados no mesmo servidor físico (não recomendo isso, mas pode ser necessário ...se os recursos estiverem escassos)
  • Certifique-se de que você será capaz de mover dados entre eles automaticamente
  • Separe os scripts de criação do banco de dados da população = Deve ser sempre possível recriar o banco de dados do zero e preenchê-lo (a partir da versão antiga do banco de dados ou da fonte de dados externa
  • não use cadeias de conexão de código rígido no código (mesmo não nos arquivos de configuração) - use nos arquivos de configuração modelos de cadeia de conexão, que você preenche dinamicamente, cada reconfiguração da camada de aplicativo que precisa ser recompilada é RUIM
  • use controle de versão de banco de dados e controle de versão de objetos de banco de dados - se você puder pagar, use produtos prontos, se não, desenvolva algo por conta própria
  • rastreie cada alteração DDL e salve-a em alguma tabela de histórico ( exemplo aqui )
  • Backups DIÁRIOS!Teste o quão rápido você seria capaz de restaurar algo perdido em um backup (use scripts de restauração automática
  • mesmo seu banco de dados DEV e o PROD têm exatamente o mesmo script de criação, você terá problemas com os dados, então permita que os desenvolvedores criem a cópia exata do prod e brinquem com ele (eu sei que receberei pontos negativos por este, mas mude no a mentalidade e o processo de negócios custarão muito menos quando a merda chegar ao ventilador - então, force os programadores a assinar legalmente tudo o que fizer, mas garanta este

Isso é algo com o qual estou constantemente insatisfeito - nossa solução para esse problema.Durante vários anos mantivemos um script de mudança separado para cada versão.Este script conteria os deltas da última versão de produção.A cada lançamento do aplicativo, o número da versão aumentaria, resultando em algo como o seguinte:

  • dbChanges_1.sql
  • dbChanges_2.sql
  • ...
  • dbChanges_n.sql

Isso funcionou bem até que começamos a manter duas linhas de desenvolvimento:Trunk/Mainline para novos desenvolvimentos e um branch de manutenção para correções de bugs, melhorias de curto prazo, etc.Inevitavelmente, surgiu a necessidade de fazer alterações no esquema da filial.Neste ponto, já tínhamos dbChanges_n+1.sql no Trunk, então acabamos optando por um esquema como o seguinte:

  • dbChanges_n.1.sql
  • dbChanges_n.2.sql
  • ...
  • dbChanges_n.3.sql

Novamente, isso funcionou bem, até que um dia olhamos e vimos 42 scripts delta na linha principal e 10 no branch.ARGH!

Hoje em dia, simplesmente mantemos um script delta e deixamos a versão do SVN - ou seja,sobrescrevemos o script a cada versão.E evitamos fazer alterações de esquema nas filiais.

Então, também não estou satisfeito com isso.Gosto muito do conceito de migrações do Rails.Fiquei bastante fascinado com LiquiBase.Ele suporta o conceito de refatorações incrementais de banco de dados.Vale a pena dar uma olhada e em breve irei analisá-lo em detalhes.Alguém tem experiência com isso?Eu ficaria muito curioso para ouvir sobre seus resultados.

Você também pode usar uma ferramenta como Comparação SQL criar scripts para a diferença entre várias versões de um banco de dados, permitindo migrar rapidamente entre versões

Temos uma configuração muito semelhante ao OP.

Os desenvolvedores desenvolvem em VMs com bancos de dados privados.

[Os desenvolvedores em breve estarão se comprometendo com filiais privadas]

Os testes são executados em diferentes máquinas (na verdade, na VM's hospedada em um servidor) [em breve será executado pelo Hudson CI Server

Teste carregando o dump de referência no banco de dados.Aplique os patches de esquema de desenvolvedores e aplique os patches de dados dos desenvolvedores

Em seguida, execute testes de unidade e de sistema.

A produção é implantada nos clientes como instaladores.

O que nós fazemos:

Pegamos um despejo de esquema do nosso banco de dados sandbox.Em seguida, um despejo de dados SQL.Nós comparamos isso com a linha de base anterior.esse par de deltas é atualizar n-1 para n.

configuramos os dumps e deltas.

Portanto, para instalar a versão N CLEAN, executamos o dump em um banco de dados vazio.Para corrigir, aplique os patches intermediários.

(Juha mencionou que a ideia do Rail de ter uma tabela registrando a versão atual do banco de dados é boa e deve tornar a instalação de atualizações menos complicada.)

Deltas e dumps devem ser revisados ​​antes do teste beta.Não consigo ver nenhuma maneira de contornar isso, pois vi desenvolvedores inserirem contas de teste no banco de dados por conta própria.

Confira a dbdeploy, já existem ferramentas Java e .net disponíveis, você pode seguir seus padrões para os layouts de arquivos SQL e a tabela de versões do esquema e escrever sua versão python.

Receio estar de acordo com outros postadores.Os desenvolvedores precisam criar scripts para suas alterações.

Em muitos casos, um simples ALTER TABLE não funcionará, você também precisa modificar os dados existentes - os desenvolvedores precisam pensar sobre quais migrações são necessárias e garantir que elas tenham scripts corretos (é claro que você precisa testar isso cuidadosamente em algum momento do o ciclo de lançamento).

Além disso, se você tiver algum bom senso, fará com que seus desenvolvedores também criem scripts de reversões para suas alterações, para que possam ser revertidas, se necessário.Isso também deve ser testado, para garantir que sua reversão não apenas seja executada sem erros, mas deixe o banco de dados no mesmo estado em que estava anteriormente (isso nem sempre é possível ou desejável, mas é uma boa regra na maioria das vezes) .

Como você conecta isso a um servidor de CI, eu não sei.Talvez o seu servidor de CI precise ter um instantâneo de construção conhecido, para o qual ele reverte todas as noites e depois aplique todas as alterações desde então.Provavelmente é melhor, caso contrário, um script de migração quebrado interromperá não apenas a compilação daquela noite, mas todas as subsequentes.

Se você estiver no ambiente .NET, a solução é Tarantino.Ele lida com tudo isso (incluindo quais scripts SQL instalar) em uma compilação NANT.

Eu escrevi uma ferramenta que (conectando-se ao Abra DBDiff) compara esquemas de banco de dados e sugerirá scripts de migração para você.Se você fizer uma alteração que exclua ou modifique dados, ocorrerá um erro, mas fornecerá uma sugestão para o script (por exemplo,quando uma coluna estiver faltando no novo esquema, ele verificará se a coluna foi renomeada e criará xx - script.sql.suggestion gerado contendo uma instrução rename).

http://code.google.com/p/migrationscriptgenerator/ Apenas SQL Server, infelizmente :( Também é bastante alfa, mas tem MUITO baixo atrito (principalmente se você combiná-lo com Tarantino ou http://code.google.com/p/simplescriptrunner/)

A maneira como eu uso é ter um projeto de scripts SQL no seu .sln.Você também tem um banco de dados db_next localmente no qual você faz alterações (usando o Management Studio ou Exportação de esquema NHibernate ou LinqToSql CreateDatabase ou alguma coisa).Em seguida, você executa o migraçãoscriptgenerator com os bancos de dados _dev e _next, que cria.os scripts de atualização SQL para migração.

Estamos usando linha de comando mysql-diff:ele gera uma diferença entre dois esquemas de banco de dados (do banco de dados ativo ou script) como script ALTER.mysql-diff é executado no início do aplicativo e, se o esquema for alterado, ele reportará ao desenvolvedor.Assim, os desenvolvedores não precisam escrever ALTERs manualmente, as atualizações de esquema acontecem de forma semiautomática.

Para banco de dados Oracle usamos oracle-ddl2svn ferramentas.

Esta ferramenta automatizou o próximo processo

  1. para cada esquema de banco de dados, obtenha ddls de esquema
  2. coloque-o sob controle de versão

alterações entre instâncias resolvidas manualmente

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