Porque é que uma aplicação autoalojada executa a mesma migração da base de dados duas vezes após uma nova implementação?

Eva Wong é a Redatora Técnica e e entusiasta residente na ZimaSpace. Uma geek de longa data com paixão por homelabs e software de código aberto, ela é especialista em traduzir conceitos técnicos complexos em guias acessíveis e práticos . Eva acredita que o auto-hospedagem deve ser divertida, não intimidante. Através dos seus tutoriais, ela capacita a comunidade adesmistificar configurações de hardware , desde a construção do seu primeiro NAS até dominar os contêineres Docker., from building their first NAS to mastering Docker containers.

Uma migração de base de dados pode ser executada duas vezes quando mais do que um caminho de arranque, contentor ou agendador considera que é responsável pelo mesmo passo de atualização.

As aplicações autoalojadas iniciam frequentemente migrações a partir de um ponto de entrada, processo Web, worker, sidecar, unidade systemd ou gancho de implementação. Após uma nova implementação, um contentor antigo pode sobrepor-se a um novo, uma política de reinício pode voltar a iniciar um migrador que falhou ou duas réplicas podem aceder à base de dados antes de uma delas registar a conclusão. O diagnóstico deve identificar todos os possíveis executores e confirmar se a estrutura de migração utiliza um bloqueio persistente ou um registo do histórico do esquema antes de iniciar qualquer reparação de dados.

Identifique todos os processos que podem iniciar a migração

Procure o comando de migração no ponto de entrada da imagem, no comando do Compose, no comando do worker, na unidade systemd, na tarefa cron, no script de implementação e no registo de arranque da aplicação. Registe os IDs dos processos e os nomes dos contentores nos dois momentos de execução.

O Docker Compose pode iniciar serviços de acordo com as dependências declaradas, mas a ordem de arranque, por si só, não torna uma migração ao nível da aplicação responsabilidade exclusiva de um único processo. As orientações oficiais sobre a ordem de arranque mostram por que motivo a disponibilidade de uma base de dados e a atribuição exclusiva da migração são condições distintas.

Se o mesmo comando aparecer no ponto de entrada Web e num serviço de migração dedicado, remova um dos responsáveis. Se existir apenas um comando, continue verificando as réplicas, os ciclos de reinício e os registos do estado da migração.

Verifique a sobreposição de contentores antigos e novos

Apresente os contentores em execução, a reiniciar, terminados e órfãos durante a implementação. Compare os nomes dos projetos, os nomes dos serviços, os IDs dos contentores e os carimbos de data e hora de criação.

O systemd documenta que a política de reinício de um serviço pode voltar a iniciar um comando que falhou, de acordo com as definições da unidade. O seu modelo de reinício de serviços ajuda a explicar por que motivo um iniciador no anfitrião pode executar novamente a migração depois de a tentativa dentro do contentor terminar com um código diferente de zero.

Remova os executores órfãos confirmados apenas depois de preservar os respetivos registos. Um segundo carimbo de data e hora de migração pouco depois do primeiro indica frequentemente uma nova tentativa, e não uma tarefa agendada separadamente.

Utilize um bloqueio da base de dados antes de aplicar alterações ao esquema

Determine se a aplicação adquire um bloqueio ao nível da base de dados antes de ler o estado da migração e aplicar alterações. Teste duas tentativas de arranque simultâneas num ambiente descartável.

O PostgreSQL disponibiliza bloqueios consultivos para coordenação definida pela aplicação, permitindo que um executor de migração impeça outro de prosseguir, mesmo quando ambos arrancam quase ao mesmo tempo.

O bloqueio deve abranger toda a janela de decisão e execução. Verificar a versão atual do esquema antes de adquirir o bloqueio ainda permite que dois executores escolham a mesma migração pendente.

Verifique a semântica dos bloqueios no MySQL ou MariaDB

Para aplicações compatíveis com MySQL, verifique se a ferramenta de migração utiliza um bloqueio nomeado, uma transação ou uma tabela de bloqueios e se a ligação permanece ativa durante toda a migração.

O MySQL documenta bloqueios nomeados associados à ligação, que são libertados quando a sessão proprietária termina e, por isso, têm de ser readquiridos com segurança após uma falha ou reinício.

Uma falha da ligação pode libertar o bloqueio antes de a estrutura de migração registar a conclusão. Compare os registos da base de dados com os carimbos de data e hora de reinício dos contentores para identificar esta sequência.

Inspecione a tabela do histórico da estrutura de migração

Apresente os identificadores das migrações, a ordem de execução, os indicadores de sucesso, as somas de verificação e os carimbos de data e hora. Compare as duas execuções registadas com os dados efetivamente confirmados na base de dados.

O Flyway utiliza uma tabela de histórico do esquema para acompanhar as migrações aplicadas e os respetivos estados.

Se a primeira execução tiver alterado o esquema, mas tiver falhado antes de registar o sucesso, a segunda execução pode tentar novamente uma migração que não foi concebida para ser idempotente. Repare o histórico apenas depois de comparar o esquema real com o resultado esperado da migração.

Verifique a identidade do changelog e as alterações nas somas de verificação

Compare os nomes dos ficheiros de migração, os IDs, os autores, os caminhos e as somas de verificação antes e depois da atualização da imagem. Determine se a imagem contém entradas de changelog duplicadas ou renomeadas.

O Liquibase regista as alterações executadas na tabela DATABASECHANGELOG, na qual a identidade da alteração depende do respetivo ID, autor e caminho do ficheiro.

Mover um ficheiro de changelog ou regenerar identificadores pode fazer com que trabalho antigo pareça novo, mesmo quando o SQL é semelhante. Restaure uma identidade de migração estável em vez de eliminar manualmente intervalos amplos do histórico.

Faça uma nova implementação com um único responsável pela migração e verifique a idempotência

Escolha um único responsável pela migração, adicione um bloqueio persistente, mantenha os serviços Web e worker à espera da conclusão com sucesso e faça uma nova implementação numa cópia de teste da base de dados.

O artigo da ZimaSpace sobre limites de agendamento dos contentores apresenta a regra relacionada: uma tarefa de manutenção deve ter um único responsável de execução comprovado.

O problema está resolvido quando os arranques simultâneos ou repetidos produzem uma única migração aplicada, um único registo persistente no histórico e nenhuma segunda alteração ao esquema após o reinício.

Perguntas frequentes

Executar uma migração duas vezes danifica sempre a base de dados?

Não. As migrações idempotentes podem detetar com segurança objetos existentes, mas transformações de dados não idempotentes, criação de índices ou alterações de colunas podem falhar ou duplicar dados.

Todas as réplicas Web devem poder executar migrações?

Apenas quando a estrutura fornece uma coordenação fiável ao nível da base de dados. Um responsável dedicado e executado uma única vez é mais fácil de auditar numa implementação num servidor doméstico.

Posso marcar manualmente a migração como concluída?

Apenas depois de provar que o esquema e os dados em produção correspondem ao resultado esperado da migração. Editar primeiro o histórico pode ocultar uma alteração parcialmente aplicada.

Suporte e Dicas

Mais para Ler

Get More Builds Like This

Stay in the Loop

Get updates from Zima - new products, exclusive deals, and real builds from the community.

Stay in the Loop preferences

We respect your inbox. Unsubscribe anytime.