Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Crie um índice em uma enorme tabela de produção MySQL sem bloqueio de tabela

[2017] Atualização:o 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 descartado. 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 impasse que cancelava a instrução INSERT, UPDATE ou DELETE na tabela.

[2015] Atualizando índices de tabela bloqueia gravações no MySQL 5.5


Da resposta acima:

"Se você estiver usando uma versão superior a 5.1, os í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 é ****FALSO**** (pelo menos para tabelas MyISAM / InnoDB, que é o que 99,999% das pessoas usam. Edição em cluster é diferente.)

Fazer operações UPDATE em uma tabela irá BLOQUEAR enquanto o índice está sendo criado. MySQL é muito, muito estúpido sobre isso (e algumas outras coisas).

Roteiro 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 a 6ª operação é bloqueada pelos ~400ms necessários para concluir 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

Atualizando o esquema do MySQL sem tempo de inatividade


Até agora, há apenas um método que conheço para atualizar um esquema MySql e não sofrer uma interrupção de disponibilidade. Mestres circulares:
  • O mestre A tem seu banco de dados MySQL rodando nele
  • 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)
  • Realize a atualização do esquema no mestre B. Ele ficará para trás durante o upgrade
  • Deixe o Mestre B acompanhar. Invariante:Sua mudança de esquema DEVE ser capaz de processar comandos replicados de um esquema de downversion. As alterações de indexação se qualificam. Adições de colunas simples geralmente se qualificam. Removendo uma coluna? provavelmente não.
  • Troque ATOMICAMENTE todos os clientes do Mestre A para o Mestre B. Se você quiser estar seguro (confie em mim, você quer), você deve garantir que a última gravação em A seja replicada para B ANTES B faz sua primeira gravação. Se você permitir gravações simultâneas para mais de 2 mestres, você entenderá melhor a replicação do MySQL em um nível PROFUNDO ou estará indo para um mundo de dor. Dor extrema. Tipo, você tem uma coluna que é AUTOINCREMENTO??? você está ferrado (a menos que você 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 vai te salvar. É 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 o Mestre 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 o esquema dele para que ele se torne seu novo mestre secundário, pronto para assumir o controle caso seu mestre primário (mestre B agora) perca energia ou simplesmente morra em você.
  • l>

Uma maneira fácil de atualizar o esquema não é. Praticável em um ambiente de produção sério; Sim, ele é. Por favor, 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.

A pesquisa no Google me levou a este artigo que descreve uma técnica semelhante. Melhor ainda, eles 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 Eu linkei acima fala sobre uma ferramenta, pt -mudança de esquema online , que funciona da seguinte forma:
  • Crie uma nova tabela com a mesma estrutura da original.
  • Atualize o esquema na nova tabela.
  • Adicione um acionador na tabela original para que as alterações sejam mantidas em sincronia com a cópia
  • Copiar linhas em lotes da tabela original.
  • Mova a mesa original para fora do caminho e substitua por uma nova mesa.
  • Retire a tabela antiga.

Eu mesmo nunca testei a ferramenta. YMMV

RDS


Atualmente, estou usando o MySQL por meio do RDS da Amazon . É um serviço realmente bacana que envolve e gerencia o MySQL, permitindo que você adicione novas réplicas de leitura com um único botão e atualize de forma transparente o banco de dados em SKUs de hardware. É muito conveniente. Você não tem acesso SUPER ao banco de dados, então não pode estragar a replicação diretamente (isso é uma benção ou maldição?). No entanto, você pode usar Promoção de réplica de leitura para fazer suas alterações de esquema em um escravo somente leitura, então promova 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 o cut-over. Você precisa reconfigurar e reiniciar seu aplicativo.