Atualização [2017]: MySQL 5.6 tem suporte para atualizações de índice online
https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-operations.html#online-ddl-index-syntax-notes
No MySQL 5.6 e superior, a tabela permanece disponível para operações de leitura e gravação enquanto o índice está sendo criado ou eliminado. A instrução CREATE INDEX ou DROP INDEX só termina depois que todas as transações que estão acessando a tabela são concluídas, para que o estado inicial do índice reflita o conteúdo mais recente da tabela. Anteriormente, modificar a tabela enquanto um índice estava sendo criado ou eliminado normalmente resultava em um conflito que cancelava a instrução INSERT, UPDATE ou DELETE na tabela.
[2015] Atualizando a tabela indica a escrita de blocos no MySQL 5.5
Da resposta acima:
"Se você estiver usando uma versão superior a 5.1 índices são criados enquanto o banco de dados está online. Portanto, não se preocupe, você não interromperá o uso do sistema de produção."
Isso é **** FALSE **** (pelo menos para tabelas MyISAM / InnoDB, que é o que 99,999% das pessoas usam. A Edição em cluster é diferente.)
Fazer operações UPDATE em uma tabela irá BLOQUEAR enquanto o índice está sendo criado. O MySQL é muito, muito estúpido sobre isso (e algumas outras coisas).
Script de teste:
(
for n in {1..50}; do
#(time mysql -uroot -e 'select * from website_development.users where id = 41225\G'>/dev/null) 2>&1 | grep real;
(time mysql -uroot -e 'update website_development.users set bio="" where id = 41225\G'>/dev/null) 2>&1 | grep real;
done
) | cat -n &
PID=$!
sleep 0.05
echo "Index Update - START"
mysql -uroot website_development -e 'alter table users add index ddopsonfu (last_name, email, first_name, confirmation_token, current_sign_in_ip);'
echo "Index Update - FINISH"
sleep 0.05
kill $PID
time mysql -uroot website_development -e 'drop index ddopsonfu on users;'
Meu servidor (InnoDB):
Server version: 5.5.25a Source distribution
Saída (observe como o sexto bloco de operação para os ~ 400ms leva para terminar a atualização do índice):
1 real 0m0.009s
2 real 0m0.009s
3 real 0m0.009s
4 real 0m0.012s
5 real 0m0.009s
Index Update - START
Index Update - FINISH
6 real 0m0.388s
7 real 0m0.009s
8 real 0m0.009s
9 real 0m0.009s
10 real 0m0.009s
11 real 0m0.009s
Vs operações de leitura que não bloqueiam (troque o comentário de linha no script):
1 real 0m0.010s
2 real 0m0.009s
3 real 0m0.009s
4 real 0m0.010s
5 real 0m0.009s
Index Update - START
6 real 0m0.010s
7 real 0m0.010s
8 real 0m0.011s
9 real 0m0.010s
...
41 real 0m0.009s
42 real 0m0.010s
43 real 0m0.009s
Index Update - FINISH
44 real 0m0.012s
45 real 0m0.009s
46 real 0m0.009s
47 real 0m0.010s
48 real 0m0.009s
Atualizar o esquema do MySQL sem tempo de inatividade
Portanto, há apenas um método que conheço para atualizar um esquema do MySql e não sofrer uma interrupção de disponibilidade. Mestres circulares:
- Master A tem seu banco de dados MySQL em execução
- Coloque o Mestre B em serviço e faça com que ele replique as gravações do Mestre A (B é um escravo de A)
- Execute a atualização do esquema no Master B. Ele ficará para trás durante a atualização
- Deixe o Mestre B alcançá-lo. Invariante: sua mudança de esquema DEVE ser capaz de processar comandos replicados de um esquema de downversion. As alterações de indexação qualificam. Geralmente, adições simples de colunas se qualificam. Removendo uma coluna? provavelmente não.
- Troque ATOMICAMENTE todos os clientes do Mestre A para o Mestre B. Se quiser ficar seguro (confie em mim, você precisa), você deve garantir que a última gravação em A seja replicada para B ANTESB faz sua primeira gravação. Se você permitir gravações simultâneas em mais de 2 mestres, ... você entende melhor a replicação do MySQL em um nível DEEP ou está caminhando para um mundo de dor. Dor extrema. Tipo, você tem uma coluna que é AUTOINCREMENT ??? você está ferrado (a menos que use números pares em um mestre e probabilidades no outro). NÃO confie na replicação do MySQL para "fazer a coisa certa". NÃO é inteligente e não irá salvá-lo. É apenas um pouco menos seguro do que copiar logs de transações binárias da linha de comando e reproduzi-los manualmente. Ainda assim, desconectar todos os clientes do antigo mestre e transferi-los para o novo mestre pode ser feito em questão de segundos, muito mais rápido do que esperar por uma atualização de esquema de várias horas.
- Agora Master B é seu novo mestre. Você tem o novo esquema. A vida é boa. Tomar uma cerveja; o pior já passou.
- Repita o processo com o Mestre A, atualizando seu esquema para que ele se torne seu novo mestre secundário, pronto para assumir no caso de seu mestre primário (mestre B agora) perder força ou simplesmente morrer em você.
Uma maneira fácil de atualizar o esquema, não é. Viável em um ambiente de produção sério; Sim, ele é. Por favor, por favor, se houver uma maneira mais fácil de adicionar um índice a uma tabela MySQL sem bloquear gravações, me avise.
Googling me levou a este artigo que descreve uma técnica semelhante. Melhor ainda, aconselham beber no mesmo ponto do procedimento (observe que escrevi minha resposta antes de ler o artigo)!
Mudança de esquema pt-online de Percona
O artigo vinculado acima fala sobre uma ferramenta, pt-online-schema-change , que funciona da seguinte maneira:
- Crie uma nova tabela com a mesma estrutura da original.
- Atualize o esquema na nova tabela.
- Adicione um gatilho na tabela original para que as alterações sejam mantidas em sincronia com a cópia
- Copie linhas em lotes da tabela original.
- Remova a mesa original do caminho e substitua por uma nova.
- Largue a mesa velha.
Nunca experimentei a ferramenta sozinho. YMMV
RDS
Atualmente, estou usando o MySQL por meio do RDS da Amazon . É um serviço realmente bacana que finaliza e gerencia o MySQL, permitindo adicionar novas réplicas de leitura com um único botão e atualizar o banco de dados de forma transparente em todos os SKUs de hardware. É muito conveniente. Você não obtém acesso SUPER ao banco de dados, então não pode atrapalhar a replicação diretamente (isso é uma bênção ou uma maldição?). No entanto, você pode usar Read Replica Promotion para fazer suas alterações de esquema em um escravo somente leitura e, em seguida, promover esse escravo para se tornar seu novo mestre. Exatamente o mesmo truque que descrevi acima, apenas muito mais fácil de executar. Eles ainda não fazem muito para ajudá-lo com a transição. Você tem que reconfigurar e reiniciar seu aplicativo.