Modificando colunas de tabelas mysql muito grandes com pouco ou nenhum tempo de inatividade

18

Periodicamente, preciso fazer alterações nas tabelas no mysql 5.1, principalmente adicionando colunas. Muito simples com o comando alter table. Mas minhas tabelas têm até 40 milhões de linhas agora e estão crescendo rapidamente ... Portanto, esses comandos alter table levam várias horas. Dentro de alguns meses, eles levarão dias, eu acho.

Como estou usando o Amazon RDS, não posso ter servidores escravos para brincar e depois promover para dominar. Então, minha pergunta é se existe uma maneira de fazer isso com um tempo de inatividade mínimo? Não me importo com uma operação que leve horas ou até dias se os usuários ainda puderem usar o banco de dados, é claro ... Eles podem pelo menos ler enquanto as colunas estão sendo adicionadas? O que acontece se meu aplicativo tentar escrever? Inserir ou atualizar? Se falhar imediatamente, na verdade não é tão ruim, se apenas travar e causar problemas para o servidor db, isso é um grande problema.

Esse deve ser um problema de dimensionamento bastante comum, todos precisam adicionar colunas. O que normalmente é feito em um banco de dados de produção? Escravo -> migração mestre?

Atualização - esqueci de mencionar que estou usando o mecanismo de armazenamento innodb

apptree
fonte
11
No caso de alguém ainda estar procurando uma resposta .. blog.staginginstance.com/… ^^
Coder anonymous

Respostas:

10

Periodicamente, preciso fazer alterações nas tabelas no mysql 5.1, principalmente adicionando colunas.

Não. Não mesmo. Apenas não. Deve ser uma ocasião muito rara quando este é sempre necessário.

Supondo que seus dados sejam realmente normalizados, a maneira correta de resolver o problema é adicionar uma nova tabela com um relacionamento 1: 1 à tabela base (não obrigatório na nova tabela).

Ter que adicionar colunas regularmente é geralmente um indicador de um banco de dados que não é normalizado - se o seu esquema não é normalizado, esse é o problema que você precisa corrigir.

Por fim, se seu esquema estiver realmente normalizado e você realmente continuar adicionando colunas, então:

  1. Verifique se você possui uma coluna de carimbo de data / hora no banco de dados ou se está gerando logs de replicação
  2. Crie uma cópia (B) da tabela (A)
  3. adicione as novas colunas a B (isso ainda será bloqueado com myisam)
  4. desativar transações
  5. renomeie a tabela original (A) como outra coisa (backup)
  6. renomeie a nova tabela (B) com o nome da tabela original (A)
  7. reproduzir as transações desde o início da operação a partir do log de replicação ou da tabela de backup
  8. ativar transações.
symcbean
fonte
2
Obrigado por sua abordagem passo a passo. É realmente incomum modificar tabelas? Entendo que, em vez disso, posso adicionar outra tabela com a nova coluna (no caso de precisar adicionar uma coluna) e fazer referência à tabela grande original em um relacionamento 1: 1. Mas não parece correto ter 15 tabelas 1: 1 muito grandes quando todas elas devem estar em uma tabela ... O desempenho da consulta, é claro, também sofre, sem mencionar os problemas de indexação. Eu não sou um especialista, mas meu banco de dados é bastante bem normalizada e parece natural que eu preciso modificar periodicamente ..
apptree
2
"É realmente incomum modificar tabelas?" - Sim.
symcbean
11
Não, mas pode-se argumentar que, se isso acontecer REGULAMENTE - não como parte de uma grande atualização de software -, alguém precisará ser demitido por não perceber que todas as tabelas devem estar lá em primeiro lugar. O problema / truque aqui é o "regularmente", não "Uma vez a cada dois meses".
TomTom
22
Como desenvolvedor, especialmente um que trabalha em empresas iniciantes e jovens, eu não poderia concordar menos com o symcbean e o @TomTom. As coisas mudam, os produtos mudam, os objetivos de negócios mudam e a estrutura do banco de dados precisa mudar com eles. Fornecer um bom serviço de DBA significa dizer "sim" a essas alterações e descobrir como implementá-las com eficiência. Bancos de dados fortemente normalizados são um conceito que morreu há muito tempo. Eles resultam em desempenho ruim e ciclos lentos de desenvolvimento.
usar o seguinte código
4
Incomum para mudar de tabela ??? Talvez em grandes empresas, mas na equipe ágil que acontece muitas vezes, a mudança requisitos ...
tibo
12

Eu só tive que fazer isso recentemente. O que a Amazon recomendou foi o uso do Percona Toolkit. Eu baixei e pude executar algo como:

./pt-online-schema-change h=databasenameHostName,D=databasename,t=tablename --recursion-method=none --execute --user username --password password --alter "MODIFY someColumn newDataType"

e funciona muito bem. Ele informa quanto tempo resta no processo.

Na verdade, ele cria uma nova tabela com a nova coluna e copia os dados existentes. Além disso, ele cria um gatilho para que novos dados também sejam enviados para a nova tabela. Em seguida, renomeia as tabelas automaticamente, descarta a tabela antiga e você está em funcionamento com a nova coluna e sem tempo de inatividade enquanto aguardava as atualizações.

efreedom
fonte
A equipe da Percona possui uma breve descrição sobre a ativação do recurso log_bin_trust_function_creators, por meio de grupos de parâmetros do RDS (como SET GLOBAL log_bin_trust_function_creators = 1 não funciona no RDS), exigido pela ferramenta pt-online-schema-change. Mais detalhes: percona.com/blog/2016/07/01/pt-online-schema-change-amazon-rds
user1652110
funcionou para mim #
Adiii
4

O symcbean fornece algumas recomendações sólidas .

Para responder sua pergunta, a melhor e mais fácil maneira de reduzir o impacto é replicar vários bancos de dados. Mestre duplo com um procedimento de failover apropriado que interrompe a replicação no ativo, o que permite uma alteração no inativo sem afetar o ativo.

Você poderia fazer isso em um único banco de dados ativo e minimizar o impacto usando um procedimento semelhante ao que eu detalhei nesta resposta . É certo que isso é semelhante ao que o symcbean descreveu, mas inclui detalhes técnicos. Você também pode usar um campo de incremento automático e não apenas o carimbo de data e hora.

Por fim, se seu conjunto de dados estiver crescendo tão grande, você também precisará considerar o arquivamento entre os bancos de dados OLTP e OLAP . O conjunto de dados da transação não deve ser tão grande, se você projetar adequadamente.

Warner
fonte
2

No manual: http://dev.mysql.com/doc/refman/5.1/en/alter-table.html

Na maioria dos casos, ALTER TABLE faz uma cópia temporária da tabela original. O MySQL incorpora a alteração na cópia, exclui a tabela original e renomeia a nova. Enquanto ALTER TABLE está em execução, a tabela original é legível por outras sessões. As atualizações e gravações na tabela ficam paradas até que a nova tabela esteja pronta e, em seguida, são redirecionadas automaticamente para a nova tabela sem nenhuma falha na atualização.

Portanto, a leitura funcionará bem. As gravações serão interrompidas, mas executadas posteriormente. Se você quiser evitar isso, precisará modificar o seu software.


fonte
Então, eu fiz isso e desabilitei as partes do meu site que escrevem na tabela que estou modificando agora. Até agora, recebi várias exceções "Tempo limite de espera de bloqueio excedido; tente reiniciar a transação", isso não é muito ruim. No entanto, eles estavam em operações
puramente
0

Estou em situação semelhante em que tenho que alterar 1 da minha tabela de transações, que é quase 65 GB. Eu ouço 2 soluções

  1. Use ALTER para a frente e deixe Executar (X números de horas ou dia)
  2. Verifique se você possui uma coluna de carimbo de data / hora no banco de dados ou se está gerando logs de replicação
    • Crie uma cópia (B) da tabela (A)
    • adicione as novas colunas a B (isso ainda será bloqueado com myisam)
    • desativar transações
    • renomeie a tabela original (A) como outra coisa (backup)
    • renomeie a nova tabela (B) com o nome da tabela original (A)
user144107
fonte