Atualização do banco de dados e implantação de tempo de inatividade zero

Muitos artigos foram escritos sobre a atualização de sistemas em tempo real sem interrompê-los (implantação com tempo de inatividade zero) e muitos aspectos dessa abordagem são bastante óbvios. Na minha opinião, a parte mais difícil da implantação nesse caso é atualizar os data warehouses se o contrato (esquema) for alterado. É esse aspecto que eu gostaria de considerar neste artigo.

Qualquer que seja o banco de dados - com um esquema de dados explícito como relacional ou arbitrário como NoSQL - o esquema de dados ainda está presente, mesmo no nível do aplicativo. Os dados lidos no banco de dados devem ser compreensíveis para o cliente, mesmo que o próprio repositório não imponha restrições à sua estrutura.

Suponha que um sistema com uma estrutura de dados específica e terabytes de dados no banco de dados já esteja em execução na produção. Na nova versão do sistema, precisamos alterar levemente a estrutura para implementar novos recursos ou melhorar o desempenho. Considere quais mudanças no circuito podem ocorrer:

  • Adicionando um novo campo
  • Exclusão de campo
  • Renomear campo
  • Alterações de tipo de campo
  • Transferindo um campo para outra estrutura de dados (por exemplo, no caso de desnormalização)

Adicionar um novo campo e adicionar qualquer outro objeto de banco de dados é uma alteração compatível com versões anteriores e não requer etapas adicionais em termos de implementação da implantação de tempo de inatividade zero (com uma ressalva - se esse novo campo ou objeto não depender funcionalmente de outros já armazenados no banco de dados dados). Simplesmente aplique as alterações ao banco de dados em tempo real e implante uma nova versão do código que usa os novos objetos de banco de dados.

Excluir um campo ou qualquer outro objeto de banco de dados não é uma alteração compatível com versões anteriores, mas a abordagem para sua implementação é muito simples - objetos de banco de dados desnecessários devem ser excluídos somente depois que a nova versão do sistema estiver completamente bloqueada.

Os outros três tipos de alterações são mais complexos em termos de fornecimento de implantação com tempo de inatividade zero. Em geral, todos eles podem ser executados copiando dados para outros campos / entidades e excluindo os “antigos” após a migração bem-sucedida de dados: para renomear, você pode copiar dados do campo antigo para um campo com um novo nome, excluir o campo antigo e alterar o tipo de dados. pode ser feito junto com a renomeação, etc. De uma forma ou de outra, durante um período de tempo, o banco de dados deve suportar contratos antigos e novos. Há pelo menos duas maneiras de fazer essas alterações rapidamente:

Se o banco de dados suportar gatilhos


  1. Crie gatilhos que copiam dados do local antigo para o novo em qualquer alteração / adição e os configuram na produção.
  2. Aplique um utilitário de conversão de dados que faça o mesmo, mas para todos os registros no banco de dados. Como os gatilhos já estão instalados, o utilitário não pode fazer nada mais complicado do que apenas uma atualização “fictícia” de cada registro (UPDATE table SET field = field ...). Um ponto muito importante aqui é que a ação de ler dados do local antigo e gravar no novo deve ser atômica e protegida contra alterações perdidas. Dependendo da estrutura do banco de dados, você pode usar o bloqueio pessimista via SELECT FOR UPDATE ou seus análogos ou otimista se a tabela tiver um campo com uma versão de registro.
  3. Depois que o utilitário termina seu trabalho (dependendo da quantidade de dados e da complexidade da atualização, o tempo de execução pode levar dias), já é possível instalar uma nova versão do sistema que suporta o novo esquema de dados. Nesse momento, todos os registros no banco de dados que existiam no momento em que o utilitário foi iniciado serão convertidos com êxito, e todos os novos que apareceram durante sua operação também serão convertidos por gatilhos.
  4. Exclua gatilhos e todos os campos (ou outros objetos de banco de dados) que não são mais necessários.

Se não for possível usar gatilhos (como é o caso de muitas soluções NoSQL)




  1. Crie e implante uma nova versão do aplicativo (versão temporária 1 na figura), que sempre lê no campo antigo, mas ao gravar nesse campo, ele atualiza o novo local antigo e o correspondente (na figura "C" - o antigo, "H" - novo). Coloque esta versão em Zade em todos os nós nos quais as instâncias do aplicativo estão em execução.
  2. Aplique um utilitário que copie dados do local antigo para o novo. Assim como os gatilhos, você precisa tomar medidas para evitar alterações perdidas.
  3. Crie e, após a conclusão do utilitário, instale outra versão do aplicativo (versão temporária 2), que lê dados de um novo campo, mas ainda grava em dois locais. Essa etapa é necessária, pois durante a atualização seqüencial de cada um dos nós ainda haverá uma lacuna quando as instâncias da versão anterior do aplicativo que lê o campo antigo funcionarem simultaneamente com o novo.
  4. Crie e, ao final da varredura completa da anterior, implante a versão final, que já não interage com o campo antigo.
  5. Exclua os campos antigos.

A segunda abordagem requer a criação e instalação de três versões diferentes do aplicativo, o que pode ser muito inconveniente e complicado. Em vez disso, você pode usar a alternância de recursos - para colocar a lógica das três versões em uma, mas alternar o modo dependendo do parâmetro de configuração, que idealmente pode ser alternado em tempo real. Portanto, em vez de instalar cada versão subseqüente, será suficiente alterar o valor do parâmetro (e reiniciar o serviço se a atualização da configuração em tempo real não for fornecida). Depois de concluir com êxito a instalação da versão final, todo o código relacionado à garantia da migração de dados deve ser completamente removido do ramo de trabalho, mesmo que "permaneça" ativo na produção até a próxima atualização do sistema.

É fácil perceber que garantir um tempo de inatividade zero ao atualizar o sistema é um procedimento complicado e frágil; portanto, faz sentido incomodá-lo apenas se houver um requisito correspondente da empresa. Mas mesmo que os requisitos de disponibilidade do sistema sejam bastante baixos (por exemplo, 99% ao ano e a janela para a atualização planejada do sistema seja de 24 horas), a conversão de dados necessária para instalar a nova versão ainda pode demorar mais. Portanto, você precisa estar preparado com antecedência para o uso de tais soluções se planeja armazenar grandes quantidades de dados.

Uma abordagem alternativa pode ser a rejeição intencional de alterações incompatíveis com versões anteriores no esquema do banco de dados, mas, infelizmente, na prática nem sempre é possível, pois geralmente a maneira mais eficaz de melhorar o desempenho do acesso a dados é reestruturar o esquema.

Source: https://habr.com/ru/post/pt423429/


All Articles