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

Guia de armazenamento para gravação de TV em direto: capacidade, retenção e limpeza
Meça gravações reais, reserve margem de segurança, combine limites de idade e capacidade e confirme que o programa elegível mais antigo é removido antes...

Fluxo de recuperação de metadados de multimédia doméstica após o restauro de uma base de dados
Proteja o estado restaurado, verifique a identidade e os caminhos dos ficheiros multimédia e, em seguida, corrija as capas ou correspondências em falta numa...

Lista de verificação de compatibilidade do cliente Jellyfin para áudio, vídeo e legendas
Teste ficheiros representativos, uma variável de cada vez, e registe Direct Play, remux, conversão de áudio, transcodificação de vídeo ou falha para cada cliente.

