Como evitar um tiro no pé usando Liquibase

Nunca aconteceu antes, e aqui vamos nós de novo!

No nosso próximo projeto, decidimos usar o Liquibase desde o início para evitar problemas no futuro. Acontece que nem todos os jovens membros da equipe sabem como usá-lo corretamente. Realizei um workshop interno, que resolvi transformar em artigo.

O artigo inclui dicas úteis e uma descrição das três armadilhas mais óbvias nas quais você pode cair ao trabalhar com ferramentas de migração de banco de dados relacional, em particular o Liquibase. Projetado para desenvolvedores Java nos níveis Junior e Middle; para desenvolvedores mais experientes pode ser interessante estruturar e repetir o que provavelmente já é conhecido.

Como evitar um tiro no pé usando Liquibase

Liquibase e Flyway são as principais tecnologias concorrentes para resolver problemas de controle de versão de estruturas relacionais no mundo Java. O primeiro é totalmente gratuito, na prática é o mais escolhido para uso, por isso o Liquibase foi escolhido como herói da publicação. No entanto, algumas das práticas descritas podem ser universais, dependendo da arquitetura da sua aplicação.

As migrações de estruturas relacionais são uma forma forçada de lidar com a fraca flexibilidade dos armazenamentos de dados relacionais. Na era da moda OOP, o estilo de trabalhar com bancos de dados significava que descreveríamos o esquema uma vez e não tocaríamos nele novamente. Mas a realidade é que as coisas sempre mudam, e mudanças na estrutura da tabela são necessárias com bastante frequência. Naturalmente, o processo em si pode ser doloroso e desagradável.

Não vou me aprofundar na descrição da tecnologia e nas instruções para adicionar uma biblioteca ao seu projeto; alguns artigos foram escritos sobre este tópico:

Além disso, já existia um excelente artigo sobre o tema dicas úteis:

Dicas

Quero partilhar os meus conselhos e comentários, que nasceram do suor, do sangue e da dor da resolução dos problemas da migração.

1. Antes de começar a trabalhar, você deve se familiarizar com a seção de melhores práticas em On-line Liquibase

São descritas coisas simples, mas muito importantes, sem as quais o uso da biblioteca pode complicar sua vida. Por exemplo, uma abordagem não estruturada para gerenciar conjuntos de alterações, mais cedo ou mais tarde, levará à confusão e a migrações interrompidas. Se você não implementar alterações mutuamente dependentes na estrutura do banco de dados e na lógica de serviço ao mesmo tempo, há uma grande probabilidade de que isso leve a testes vermelhos ou a um ambiente corrompido. Além disso, as recomendações para uso do Liquibase no site oficial contêm uma cláusula sobre o desenvolvimento e teste de scripts de rollback junto com os principais scripts de migração. Bem, no artigo https://habr.com/ru/post/178665/ Existem exemplos de código relacionados a migrações e ao mecanismo de reversão.

2. Se você começar a usar ferramentas de migração, não permita correções manuais na estrutura do banco de dados

Como diz o ditado: “Uma vez Persil, sempre Persil”. Se a base da sua aplicação começar a ser gerenciada pelo Liquibase, quaisquer alterações manuais levarão imediatamente a um estado inconsistente e o nível de confiança nos conjuntos de alterações se tornará zero. Os riscos potenciais incluem várias horas gastas na restauração do banco de dados; na pior das hipóteses, um servidor morto. Se você tem um arquiteto DBA da “velha escola” em sua equipe, explique a ele com paciência e atenção como as coisas serão ruins se ele simplesmente editar o banco de dados de acordo com seu próprio entendimento de um desenvolvedor SQL condicional.

3. Se o conjunto de alterações já foi enviado para o repositório, evite editar

Se outro desenvolvedor fez um pull e aplicou um conjunto de alterações, que será editado posteriormente, ele com certeza se lembrará de você com uma palavra gentil quando receber um erro ao iniciar o aplicativo. Se a edição do conjunto de alterações de alguma forma vazar para o desenvolvimento, você terá que seguir o caminho escorregadio dos hotfixes. A essência do problema está na validação das alterações por hash sum - principal mecanismo do Liquibase. Ao editar o código do conjunto de alterações, a quantidade de hash muda. A edição de conjuntos de alterações só é possível quando é possível implantar todo o banco de dados do zero sem perder dados. Neste caso, refatorar o código SQL ou XML pode, pelo contrário, facilitar a vida e tornar as migrações mais legíveis. Um exemplo seria uma situação em que, no início da aplicação, o esquema do banco de dados de origem fosse acordado dentro da equipe.

4. Verifique backups de banco de dados, se possível

Aqui, eu acho, tudo está claro. Se de repente a migração não tiver êxito, tudo poderá ser devolvido. O Liquibase possui uma ferramenta para reverter alterações, mas os scripts de reversão também são escritos pelo próprio desenvolvedor e podem ter problemas com a mesma probabilidade que os scripts do conjunto de alterações principal. Isso significa que é útil jogar pelo seguro com backups em qualquer caso.

5. Use backups de banco de dados comprovados em desenvolvimento, se possível

Se isso não contrariar contratos e privacidade, não há dados pessoais no banco de dados e não pesa nem dois sóis - antes de usá-lo em servidores de migração ao vivo, você pode verificar como funcionará na máquina do desenvolvedor e calcular quase 100% dos potenciais problemas durante a migração.

6. Comunique-se com outros desenvolvedores da equipe

Em um processo de desenvolvimento bem organizado, todos na equipe sabem quem está fazendo o quê. Na realidade, muitas vezes este não é o caso, portanto, se você estiver preparando alterações na estrutura do banco de dados como parte de sua tarefa, é aconselhável notificar adicionalmente toda a equipe sobre isso. Se alguém estiver fazendo alterações paralelamente, você deve organizar cuidadosamente. Vale a pena comunicar com os colegas depois de terminar o trabalho, e não apenas no início. Muitos problemas potenciais com conjuntos de alterações podem ser resolvidos na fase de revisão do código.

7. Pense no que você está fazendo!

Pareceria um conselho evidente que se aplica a qualquer situação. Porém, muitos problemas poderiam ter sido evitados se o desenvolvedor tivesse analisado mais uma vez o que está fazendo e o que isso poderia afetar. Trabalhar com migrações sempre requer atenção e precisão adicionais.

Armadilhas

Vejamos agora as armadilhas típicas nas quais você pode cair se não seguir os conselhos acima e o que exatamente você deve fazer?

Situação 1: Dois desenvolvedores estão tentando adicionar novos conjuntos de alterações ao mesmo tempo

Como evitar um tiro no pé usando Liquibase
Vasya e Petya desejam criar uma versão 4 do conjunto de alterações, sem se conhecerem. Eles fizeram alterações na estrutura do banco de dados e emitiram uma solicitação pull com diferentes arquivos de conjunto de alterações. O seguinte mecanismo de ação é proposto:

Como decidir

  1. De alguma forma, os colegas devem concordar sobre a ordem em que seus conjuntos de alterações devem ser executados, por exemplo, Petin deve ser aplicado primeiro.
  2. Alguém deveria adicionar o segundo a si mesmo e marcar o conjunto de alterações de Vasya com a versão 5. Isso pode ser feito por meio do Cherry Pick ou de uma mesclagem simples.
  3. Após as alterações, você deve definitivamente verificar a validade das ações tomadas.
    Na verdade, os mecanismos do Liquibase permitirão que você tenha dois conjuntos de alterações da versão 4 no repositório, para que você possa deixar tudo como está. Ou seja, você simplesmente terá duas alterações na versão 4 com nomes diferentes. Com essa abordagem, posteriormente fica muito difícil navegar pelas versões do banco de dados.

Além disso, Liquibase, assim como a casa dos hobbits, guarda muitos segredos. Uma delas é a chave validCheckSum, que apareceu na versão 1.7 e permite especificar um valor hash válido para um conjunto de alterações específico, independentemente do que está armazenado no banco de dados. Documentação https://www.liquibase.org/documentation/changeset.html diz o seguinte:

Adicione uma soma de verificação considerada válida para este changeSet, independentemente do que estiver armazenado no banco de dados. Usado principalmente quando você precisa alterar um changeSet e não deseja que erros sejam gerados em bancos de dados nos quais ele já foi executado (não é um procedimento recomendado)

Sim, sim, este procedimento não é recomendado. Mas às vezes um mago de luz forte também domina técnicas sombrias

Situação 2: Migração que depende de dados

Como evitar um tiro no pé usando Liquibase

Vamos supor que você não tenha a capacidade de usar backups de banco de dados de servidores ativos. Petya criou um conjunto de alterações, testou-o localmente e, com total confiança de que estava certo, fez uma solicitação pull ao desenvolvedor. Por precaução, o líder do projeto esclareceu se Petya o havia verificado e depois o adicionou. Mas a implantação no servidor de desenvolvimento caiu.

Na verdade, isso é possível e ninguém está imune a isso. Isso acontece se as modificações na estrutura da tabela estiverem de alguma forma vinculadas a dados específicos do banco de dados. Obviamente, se o banco de dados de Petya estiver preenchido apenas com dados de teste, ele poderá não cobrir todos os casos problemáticos. Por exemplo, ao excluir uma tabela, verifica-se que existem registros em outras tabelas por Chave Estrangeira que estão relacionados aos registros daquela que está sendo excluída. Ou, ao alterar um tipo de coluna, nem 100% dos dados podem ser convertidos para o novo tipo.

Como decidir

  • Escreva scripts especiais que serão usados ​​uma vez junto com a migração e coloque os dados no formato adequado. Esta é uma forma geral de resolver o problema de transferência de dados para novas estruturas após a aplicação das migrações, mas algo semelhante pode ser aplicado antes, em casos especiais. Esse caminho, é claro, nem sempre está disponível, porque a edição de dados em servidores ativos pode ser perigosa e até destrutiva.
  • Outra maneira difícil é editar um conjunto de alterações existente. A dificuldade é que todas as bases de dados onde já foi aplicado na forma existente terão que ser restauradas. É bem possível que toda a equipe de back-end seja forçada a implementar localmente o banco de dados do zero.
  • E a forma mais universal é transferir o problema dos dados para o ambiente do desenvolvedor, recriando a mesma situação e adicionando um novo conjunto de alterações, ao quebrado, que irá contornar o problema.
    Como evitar um tiro no pé usando Liquibase

Em geral, quanto mais o banco de dados for semelhante em composição ao banco de dados do servidor de produção, menor será a chance de os problemas com migrações irem longe. E, claro, antes de enviar um conjunto de alterações para o repositório, você deve pensar várias vezes se ele quebrará alguma coisa.

Situação 3. Liquibase começa a ser usado após entrar em produção

Suponha que o líder da equipe peça a Petya para incluir o Liquibase no projeto, mas o projeto já está em produção e já existe uma estrutura de banco de dados.

Conseqüentemente, o problema é que em qualquer novo servidor ou máquina de desenvolvedor, essas tabelas devem ser recriadas do zero e o ambiente existente deve permanecer em um estado consistente, pronto para aceitar novos conjuntos de alterações.

Como decidir

Existem também várias maneiras:

  • A primeira e mais óbvia é ter um script separado que deve ser aplicado manualmente ao inicializar um novo ambiente.
  • A segunda é menos óbvia, faça uma migração do Liquibase que esteja em outro contexto do Liquibase e aplique-a. Você pode ler mais sobre o Contexto Liquibase aqui: https://www.liquibase.org/documentation/contexts.html. Em geral, este é um mecanismo interessante que pode ser utilizado com sucesso, por exemplo, para testes.
  • O terceiro caminho consiste em várias etapas. Primeiro, uma migração deve ser criada para tabelas existentes. Em seguida, deve ser aplicado a algum ambiente e assim será obtido seu hash sum. O próximo passo é inicializar tabelas vazias do Liquibase em nosso servidor não vazio, e na tabela com o histórico de uso dos conjuntos de alterações, você pode colocar manualmente um registro sobre o conjunto de alterações “como se aplicado” com as alterações já existentes no banco de dados . Assim, em um servidor existente, a contagem regressiva do histórico começará a partir da versão 2, e todos os novos ambientes se comportarão de forma idêntica.
    Como evitar um tiro no pé usando Liquibase

Situação 4. As migrações tornam-se enormes e não têm tempo para serem concluídas

No início do desenvolvimento do serviço, via de regra, o Liquibase é utilizado como dependência externa, e todas as migrações são processadas no início da aplicação. No entanto, com o tempo, você poderá se deparar com os seguintes casos:

  • As migrações tornam-se enormes e demoram muito para serem concluídas.
  • Há necessidade de migração em ambientes distribuídos, por exemplo, em diversas instâncias de servidores de banco de dados simultaneamente.
    Nesse caso, aplicar migrações por muito tempo resultará em um tempo limite quando o aplicativo for iniciado. Além disso, aplicar migrações a cada instância de aplicativo separadamente pode resultar na falta de sincronia de diferentes servidores.

Como decidir

Nesses casos, seu projeto já é grande, talvez até adulto, e o Liquibase passa a atuar como uma ferramenta externa separada. O fato é que o Liquibase como biblioteca é compilado em um arquivo jar, podendo funcionar como dependência dentro de um projeto ou de forma independente.

No modo autônomo, você pode deixar a implementação de migrações para seu ambiente de CI/CD ou para os administradores de sistema e especialistas em implantação. Para fazer isso você precisará da linha de comando do Liquibase https://www.liquibase.org/documentation/command_line.html. Neste modo, é possível iniciar a aplicação após realizadas todas as migrações necessárias.

Jogar aviator online grátis: hack aviator funciona

Na verdade, pode haver muito mais armadilhas ao trabalhar com migrações de banco de dados, e muitas delas exigem uma abordagem criativa. É importante compreender que se você usar a ferramenta corretamente, a maioria dessas armadilhas poderá ser evitada. Especificamente, tive que lidar com todos os problemas listados de diferentes formas, e alguns deles foram resultado de meus erros. Principalmente isso acontece, é claro, devido à desatenção, mas às vezes devido à incapacidade criminosa de usar a ferramenta.

Fonte: habr.com

Adicionar um comentário