temos lutado com um problema nos últimos dias. Queremos adicionar um índice a uma tabela enorme com 60 milhões de registros. No início, tentamos adicioná-lo com a sintaxe básica do MySQL. Mas isso obstruiu nosso banco de dados de produção. Essa tabela é usada com muita frequência em consultas de produção. Então tudo sofreu.
Nosso banco de dados está hospedado no AWS RDS. É Mysql 5.7. Estamos usando Laravel como nosso framework PHP
A próxima coisa que lemos foi que podemos copiar a tabela atual para uma nova. Em seguida, adicione o índice à nova tabela. Em seguida, mude o modelo laravel para usar a nova tabela. Achamos que fazia sentido e que seria bastante fácil
Mas copiar os dados da tabela de uma tabela para a nova demorava muito tempo. Nossos cálculos mostraram que levaria dias. Tentamos usar Laravel e também comandos SQL. Mas foi muito lento de qualquer maneira.
Depois tentamos exportar os dados como CSV e importá-los, mas, novamente, muito lento. Os primeiros milhões de registros seriam inseridos rapidamente, mas a inserção da tabela se tornaria extremamente lenta.
Finalmente tentamos mysqldump
e percebemos que ele também bloqueia a nova tabela durante a inserção, talvez por isso seja rápido o suficiente. Demorou cerca de 6 horas para copiar a tabela para uma nova. MAS faltavam 2 milhões de registros neste método. Também verificamos quantos registros entraram na tabela existente durante a exportação/importação, eram apenas cerca de 100K. Portanto, faltavam 1,9 milhão de registros na exportação/importação e não conseguimos descobrir o porquê.
Depois de passar por todos esses caminhos diferentes, decidimos colocar o aplicativo em tempo de inatividade e adicionar o índice na enorme mesa
Eu queria saber se outras pessoas também enfrentam esse problema? Existe uma maneira de adicionar índices em uma tabela enorme sem causar tempo de inatividade na produção? Ou existe uma maneira mais rápida de copiar uma grande tabela MySQL sem perda de dados?
Para este exemplo, digamos que você tenha o seguinte no banco de dados mydb
e você deseja criar dois índices da seguinte maneira:
Existem dois métodos que você realmente precisa examinar.
MÉTODO #1: Use DDL Online
Você pode iniciar sua alteração com ALTER TABLE usando a seguinte sintaxe
Como você está adicionando um índice e não alterando nenhum tipo de dados em nenhuma coluna, os dados das linhas serão verificados para gerar páginas de índice.
MÉTODO # 2: Use pt-online-schema-change
Esta ferramenta tem sido um salva-vidas para muitos ao longo dos anos
Você precisa executar isso em duas fases
FASE #1: Teste a seco
Esta fase, que é basicamente uma verificação de sintaxe, leva menos de 5 segundos para ser executada
FASE #2: Corrida ao Vivo
Aqui está o que pt-online-schema-change fará
pt-online-schema-change cria três gatilhos
Então, pt-online-schema-change copiará as linhas de mytable para _mytable_new. Se houver INSERTs, UPDATEs ou DELETEs durante a execução, os gatilhos preencherão essas alterações em _mytable_new
Depois que cada linha for copiada para _mytable_new, pt-online-schema-change fará isso
Os três gatilhos são eliminados no final.
Você pode ver essas etapas no arquivo dryrun.log
Você pode ver o progresso em liverun.log
NOTA: Execute o liverun em uma sessão de tela ou em um processo em segundo plano