Solução de Problemas Comuns em Migração MySQL e Erros de Transferência de Dados
Enfrentando obstáculos durante sua migração MySQL? Este guia fornece dicas especializadas de solução de problemas para erros comuns de transferência de dados, falhas de compatibilidade e gargalos de desempenho. Aprenda a lidar com conflitos de chave estrangeira, resolver corrupção de conjunto de caracteres (usando utf8mb4), gerenciar disparidades de versão (como MySQL 5.7 para 8.0) e otimizar importações de dados em massa usando técnicas eficazes de `mysqldump` e configurações de servidor. Garanta uma transição de banco de dados contínua e confiável com esta abordagem prática e passo a passo.
Solução de Problemas Comuns em Migração MySQL e Erros de Transferência de Dados
As migrações MySQL falham de algumas maneiras familiares. A importação para em uma chave estrangeira. Caracteres se transformam em pontos de interrogação. Um dump do MySQL 5.7 não carrega corretamente no MySQL 8.0. Os dados carregam, mas a aplicação quebra porque uma rotina armazenada, trigger, usuário ou modo SQL não veio como você esperava. Nenhum desses problemas é incomum, mas são muito mais fáceis de lidar quando você trata a migração como um processo repetível em vez de uma cópia única.
O melhor hábito de migração é ensaiar. Faça um backup real, restaure-o em um destino de staging, execute os mesmos comandos de importação que planeja usar em produção e anote cada aviso. Um ensaio informa se seu dump está completo, se a configuração de destino é compatível e quanto tempo o carregamento realmente leva. Também fornece um plano de reversão mais realista do que "vamos descobrir durante a janela de manutenção".
Comece Identificando o Tipo de Falha
Quando uma migração quebra, não comece a alterar variáveis do servidor aleatoriamente. Coloque o erro em um destes baldes:
- Compatibilidade: diferenças de versão, palavras reservadas, recursos removidos, padrões alterados.
- Codificação: incompatibilidades de conjunto de caracteres e collation.
- Restrições: chaves estrangeiras, chaves únicas, restrições de verificação, colunas geradas.
- Cobertura de objetos: triggers, rotinas, eventos, visões, usuários ou permissões ausentes.
- Desempenho: importação muito lenta, disco cheio, logs binários crescendo, índices demorando muito.
- Comportamento da aplicação: dados importados, mas consultas ou gravações se comportam de forma diferente.
Essa classificação fornece o próximo comando a ser executado. Um erro de chave duplicada e um emoji corrompido são ambos "problemas de migração", mas têm causas completamente diferentes.
Incompatibilidades de Versão: MySQL 5.7 para 8.0 e Saltos Semelhantes
Atualizações de versão principal são onde muitas surpresas aparecem. O MySQL 8.0 alterou padrões, palavras reservadas, comportamento de autenticação, detalhes internos do dicionário de dados e comportamento do otimizador em comparação com o 5.7. Alguma sintaxe antiga ainda funciona; outra não. O MariaDB adiciona outra camada de compatibilidade porque não é um substituto direto para todos os recursos do MySQL.
Antes da migração, capture as configurações de origem:
SHOW VARIABLES LIKE 'version';
SHOW VARIABLES LIKE 'sql_mode';
SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';
No destino, execute as mesmas verificações e compare. sql_mode merece atenção especial. Um dump que carrega em uma origem permissiva pode falhar em um destino mais restrito com erros como datas inválidas, padrões ausentes para colunas NOT NULL ou datas zero que não são mais aceitas no modo de destino.
Se você encontrar um erro como:
ERROR 1067 (42000): Invalid default value for 'created_at'
não relaxe imediatamente sql_mode para sempre. Primeiro inspecione a definição da tabela e os dados. Você pode precisar corrigir padrões, converter datas zero ou atualizar suposições da aplicação. Corresponder temporariamente o sql_mode de origem durante a importação pode ajudar a concluir uma restauração em etapas, mas a produção deve avançar para um modo conhecido e explícito no qual sua aplicação foi testada.
Palavras reservadas também podem quebrar esquemas antigos. Uma coluna ou tabela chamada rank, groups ou outra palavra reservada mais recente pode precisar de aspas ou renomeação. Se o erro aparecer em DDL, inspecione a declaração exata do dump e teste uma versão corrigida no destino.
Problemas com Plugin de Autenticação
Uma migração que inclui uma transição de aplicação frequentemente falha antes que qualquer consulta seja executada porque os clientes não conseguem autenticar. O MySQL 8.0 comumente usa caching_sha2_password por padrão, enquanto clientes mais antigos podem esperar mysql_native_password.
Verifique os usuários de destino:
SELECT user, host, plugin FROM mysql.user;
A melhor correção geralmente é atualizar a biblioteca do cliente ou driver. Se isso não for possível antes da transição, você pode precisar de uma conta de compatibilidade temporária:
ALTER USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'new_secret';
Trate isso como uma decisão de compatibilidade, não uma prática recomendada genérica. As configurações de autenticação afetam a segurança, e a resposta correta depende das versões do seu cliente e do modelo de risco.
Problemas de Conjunto de Caracteres e Collation
Problemas de conjunto de caracteres são dolorosos porque a importação pode terminar com sucesso enquanto os dados já estão danificados. O sintoma clássico é ?, mojibake, caracteres acentuados quebrados ou inserções falhas envolvendo emoji.
Verifique as definições do banco de dados e tabela de origem:
SELECT schema_name, default_character_set_name, default_collation_name
FROM information_schema.SCHEMATA
WHERE schema_name = 'appdb';
Verifique também as colunas:
SELECT table_name, column_name, character_set_name, collation_name
FROM information_schema.COLUMNS
WHERE table_schema = 'appdb'
AND character_set_name IS NOT NULL;
Para a maioria das aplicações modernas, utf8mb4 é o conjunto de caracteres de destino correto porque suporta toda a gama Unicode, incluindo emoji. O nome utf8 mais antigo do MySQL não é o mesmo que UTF-8 completo em versões mais antigas; é comumente um conjunto de caracteres de 3 bytes.
Ao despejar e importar, seja explícito:
mysqldump --default-character-set=utf8mb4 -u usuario -p appdb > appdb.sql
mysql --default-character-set=utf8mb4 -u usuario -p appdb < appdb.sql
Se os dados de origem são realmente latin1, não declare cegamente como utf8mb4 e espere. Primeiro determine se os bytes são válidos na codificação de origem. Alguns sistemas antigos contêm dados "duplamente codificados" onde a coluna afirma um conjunto de caracteres, mas a aplicação armazenou bytes de outro. Isso precisa de uma conversão testada, não de uma busca e substituição global.
Diferenças de collation também podem alterar o comportamento. Ordem de classificação, comparações de unicidade e sensibilidade a maiúsculas/minúsculas podem diferir entre collations. Se um índice único falhar durante a migração, verifique se a collation de destino trata duas strings como iguais quando a origem não tratava.
Falhas de Chave Estrangeira
Erros de chave estrangeira geralmente significam uma de quatro coisas:
- Tabelas filhas foram importadas antes das tabelas pai.
- O dump é parcial e faltam linhas referenciadas.
- Os dados de origem já tinham referências inconsistentes.
- O esquema de destino difere da origem.
A solução alternativa comum para carga em massa é:
SET FOREIGN_KEY_CHECKS = 0;
-- importar dados
SET FOREIGN_KEY_CHECKS = 1;
Isso pode ser apropriado para uma restauração lógica completa de um dump confiável. Não é uma ferramenta de limpeza. Reativar FOREIGN_KEY_CHECKS não revalida completamente cada linha existente como muitos supõem, então você pode importar relacionamentos ruins e não notar até mais tarde.
Se você está mesclando dados ou importando apenas parte de um esquema, mantenha as verificações ativadas quando possível e carregue as tabelas pai primeiro. Se você precisar desativar as verificações, execute consultas de validação depois. Por exemplo:
SELECT c.*
FROM pedidos c
LEFT JOIN clientes p ON p.id = c.cliente_id
WHERE c.cliente_id IS NOT NULL
AND p.id IS NULL
LIMIT 20;
Use consultas como essa para seus relacionamentos reais, especialmente tabelas de alto valor, como pedidos, pagamentos, contas e permissões.
Erros de Chave Duplicada
Um erro de chave duplicada significa que o destino já tem um valor que os dados recebidos tentam inserir:
ERROR 1062 (23000): Duplicate entry '123' for key 'PRIMARY'
Se o destino deve ser uma cópia exata, a correção limpa geralmente é descartar e recriar o banco de dados de destino e importar novamente. Um destino meio carregado não é um bom ponto de partida para uma segunda tentativa, a menos que seu processo tenha sido projetado para retomar.
Se você está mesclando dados, decida a política de conflito antes da importação. INSERT IGNORE esconde duplicatas pulando linhas. REPLACE INTO exclui a linha existente e insere a nova, o que pode disparar cascatas e alterar colunas de atualização automática. ON DUPLICATE KEY UPDATE é mais explícito, mas ainda precisa de regras cuidadosas.
Para migrações, prefiro tabelas de staging para mesclagens. Carregue os dados recebidos em tabelas staging_*, inspecione conflitos e depois escreva declarações deliberadas INSERT ... SELECT ou UPDATE ... JOIN. É mais lento de projetar, mas evita descartar dados silenciosamente.
Triggers, Rotinas, Eventos e Visões Ausentes
Uma migração pode parecer bem-sucedida porque tabelas e linhas existem, enquanto lógica importante do banco de dados está faltando. As opções de mysqldump importam:
mysqldump -u usuario -p \
--single-transaction \
--routines \
--triggers \
--events \
appdb > appdb.sql
Visões e rotinas podem falhar na importação por causa de contas definidoras. Uma visão pode referenciar:
DEFINER=`usuario_antigo`@`host_antigo`
Se essa conta não existir no destino, o objeto pode falhar ao criar ou falhar quando usado. Você pode criar a conta definidora necessária com privilégios apropriados ou ajustar definidores durante um processo de migração controlado. Não remova definidores cegamente sem entender o modelo de segurança da aplicação.
Após a importação, compare contagens de objetos:
SELECT ROUTINE_TYPE, COUNT(*)
FROM information_schema.ROUTINES
WHERE ROUTINE_SCHEMA = 'appdb'
GROUP BY ROUTINE_TYPE;
SELECT TRIGGER_SCHEMA, COUNT(*)
FROM information_schema.TRIGGERS
WHERE TRIGGER_SCHEMA = 'appdb'
GROUP BY TRIGGER_SCHEMA;
Verifique também eventos agendados se sua aplicação depende deles:
SHOW EVENTS FROM appdb;
Importações Lentas e Tabelas Grandes
Importações grandes geralmente são limitadas por I/O de disco, manutenção de índice, log binário, verificações de chave estrangeira ou tamanho da transação. Antes de ajustar, observe o destino:
iostat -xz 1
df -h
top
Para dumps lógicos, use inserções estendidas. mysqldump faz isso por padrão na maioria dos casos, mas confirme que você não está usando --skip-extended-insert a menos que precise de diffs legíveis por humanos mais do que velocidade.
Para importações InnoDB, um innodb_buffer_pool_size maior pode ajudar se o destino tiver memória disponível. Não o defina tão alto que o SO comece a fazer swap. Durante uma carga única, algumas equipes relaxam temporariamente configurações de durabilidade como innodb_flush_log_at_trx_commit ou desabilitam o log binário para a sessão de importação. Essas escolhas trocam recuperação de falhas ou recuperação point-in-time por velocidade, então devem ser usadas apenas quando você pode se dar ao luxo de reiniciar a importação a partir de um backup conhecido.
Se o destino também é uma fonte de replicação, tome cuidado com logs binários. Desabilitar o log binário pode acelerar a importação, mas réplicas downstream não receberão essas alterações. Em uma topologia com réplicas, decida onde a importação deve acontecer e como as alterações devem fluir antes de desligar os logs.
Para tabelas muito grandes, considere ferramentas de backup físico ou utilitários de dump e carga do MySQL Shell em vez de mysqldump simples. Dumps lógicos são portáteis e fáceis de inspecionar, mas nem sempre são o caminho mais rápido para conjuntos de dados de várias centenas de gigabytes.
Falhas de Espaço em Disco
Falhas de disco durante a migração são comuns e evitáveis. Você precisa de espaço para o arquivo de dump, os dados importados, índices, arquivos temporários, logs binários e, às vezes, armazenamento duplo enquanto as tabelas são reconstruídas.
Verifique antes da importação:
df -h
du -sh /var/lib/mysql
Dentro do MySQL, verifique os tamanhos das tabelas:
SELECT table_schema,
ROUND(SUM(data_length + index_length) / 1024 / 1024 / 1024, 2) AS size_gb
FROM information_schema.TABLES
GROUP BY table_schema
ORDER BY size_gb DESC;
Se a importação falhar porque o disco encheu, não exclua arquivos aleatórios do diretório de dados. Libere espaço com segurança, inspecione se o destino está parcialmente carregado e decida se deve reiniciar do zero.
Validação Pós-Migração
Uma migração não termina quando o comando de importação sai. Valide o resultado.
Comece com contagens de linhas para tabelas importantes:
SELECT COUNT(*) FROM clientes;
SELECT COUNT(*) FROM pedidos;
SELECT COUNT(*) FROM pagamentos;
Contagens de linhas sozinhas não são suficientes. Compare somas ou verificações para dados críticos de negócios:
SELECT COUNT(*), SUM(valor_total), MIN(data_criacao), MAX(data_criacao)
FROM pedidos;
Execute as mesmas consultas na origem e no destino durante o período de silêncio final. Para tabelas que continuam mudando durante a migração, use um congelamento planejado, recuperação de replicação ou reconciliação no nível da aplicação.
Teste fluxos de trabalho da aplicação contra o destino antes da transição:
- Login e criação de sessão.
- Criar e atualizar registros principais.
- Pesquisas e relatórios que dependem de collations ou índices.
- Jobs em segundo plano, triggers e eventos agendados.
- Verificações de permissão e ações de administrador.
O teste da aplicação importa porque o banco de dados pode ser tecnicamente importado, mas comportamentalmente errado.
Uma Lista de Verificação Prática de Triagem de Migração
Quando um erro de migração aparecer, use esta sequência:
- Salve a mensagem de erro exata e a declaração SQL com falha, se disponível.
- Identifique o balde: compatibilidade, codificação, restrição, cobertura de objetos, desempenho ou comportamento da aplicação.
- Compare versões MySQL de origem e destino,
sql_mode, conjuntos de caracteres e collations. - Para erros de restrição, inspecione as linhas pai e filho específicas ou chaves duplicadas.
- Para problemas de codificação, pare de importar até saber se os bytes de origem são válidos e como a conexão do cliente os está interpretando.
- Para importações lentas, verifique disco, memória, logs binários e manutenção de índice antes de alterar variáveis aleatórias.
- Após uma correção, execute novamente a migração em staging antes de aplicá-la em produção.
A migração MySQL mais confiável é aquela que você pode descartar e repetir. Mantenha comandos em um script, mantenha alterações de configuração documentadas e torne a validação parte do plano, em vez de um olhar final esperançoso.