Existe um reinício gracioso ou seguro para o mysql como para o apache httpd?

29

Eu gostaria de reiniciar o mysql normalmente, como o httpd, onde os threads são servidos antes da reinicialização. Eu não gostaria de interromper as consultas.

giorgio79
fonte

Respostas:

37

Qualquer sequência de desligamento "solicitado" no MySQL (menos de kill -9) é um tanto simples , pois as transações em andamento (em tabelas transacionais) são revertidas, mas aqui estão algumas maneiras de tornar a reinicialização o mais limpa possível.

Nota: se você estiver desligando o servidor para uma atualização, não use esse processo; em vez disso, siga o processo detalhado nesta resposta .

Caso contrário, se você estiver apenas reiniciando um servidor íntegro para poder alterar uma variável global somente leitura ou algo semelhante, eis um caminho simples:

Primeiro, ative innodb_fast_shutdownse ainda não estiver. Isso não está diretamente relacionado à graça do desligamento, mas deve trazer o servidor de volta mais rapidamente.

mysql> SHOW VARIABLES LIKE 'innodb_fast_shutdown';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| innodb_fast_shutdown | 0     |
+----------------------+-------+
1 row in set (0.00 sec)

mysql> SET GLOBAL innodb_fast_shutdown = 1;
Query OK, 0 rows affected (0.01 sec)

Em seguida, instrua o servidor a fechar todas as tabelas abertas assim que nenhuma consulta em execução estiver fazendo referência a elas. Esta etapa também não tem nada a ver com o desligamento normal, mas fará com que a etapa subsequente seja mais rápida:

mysql> FLUSH LOCAL TABLES;
Query OK, 0 rows affected (41.12 sec)

A FLUSH TABLESinstrução (com a LOCALpalavra-chave opcional , que evita uma descarga desnecessária, mas inofensiva de qualquer escravo) será bloqueada e seu prompt não retornará até que todas as tabelas possam ser fechadas. Depois que cada tabela for "liberada" (fechada), se uma consulta fizer referência posteriormente à tabela, ela será reaberta automaticamente, mas tudo bem. O que estamos realizando com esta etapa é fazer menos trabalho para a etapa final:

mysql> FLUSH TABLES WITH READ LOCK;
Query OK, 0 rows affected (13.74 sec)

mysql>

Essa instrução libera todas as tabelas (daí a vantagem de desviá-las de maneira menos disruptiva com a etapa anterior) e adquire uma trava global somente leitura (em todo o servidor).

Você não pode ter um bloqueio de leitura global até que todas as consultas de "gravação" em execução no momento (ou seja, praticamente tudo, menos SELECT) sejam concluídas. A emissão da solicitação de bloqueio permitirá que as consultas existentes sejam concluídas, mas não permitirá que novas sejam iniciadas.

Seu prompt não retorna até que você mantenha esse bloqueio global; portanto, todas as consultas em andamento quando você solicita o bloqueio podem ser concluídas e você sabe que elas foram concluídas porque você recebe o prompt de volta. Quaisquer consultas subseqüentes que tentarem escrever algo em qualquer tabela ficarão paralisadas, sem alteração de dados, aguardando indefinidamente pelo bloqueio, até ...

  • você muda de idéia sobre a reinicialização e libera a trava manualmente ( UNLOCK TABLES;)
  • você reinicia o servidor ou
  • você acidentalmente ou intencionalmente desconecta o cliente de linha de comando desse encadeamento (portanto, não faça isso). Mantenha esta janela conectada e sentada no prompt do mysql:

Resista à tentação de fechar isso.

mysql>

Esse prompt do console inativo é o que está mantendo o bloqueio global para você. Perca isso, perca a fechadura.

Em outra janela do console, reinicie o MySQL da maneira que você faria normalmente, com initscripts (por exemplo, sua variante local de service mysql.server restart) ou com o mysqladmin shutdownseguido por uma reinicialização manual.

Michael - sqlbot
fonte
O uso innodb_fast_shutdown = 1realmente garante que o MySQL inicie mais rapidamente? Olhando para os documentos, parece que isso melhora a velocidade de desligamento (ao custo da velocidade de inicialização?).
21418 Chris
@ Chris, a idéia é que isso ajude a garantir que todo o desligamento + inicialização seja o mais rápido possível, mas é um tanto curioso, já que a quantidade de trabalho que está sendo feita é teoricamente a mesma - apenas movida para o outro lado da sequência - ainda por alguma razão, sempre pareceu geralmente mais rápido em geral, como talvez haja alguma ineficiência na maneira como acontece no desligamento que não existe na inicialização. Difícil de dizer.
Michael - sqlbot
2

Em resumo, algumas das melhores práticas que devem ser consideradas antes de desligar o MySQL são:

  1. Confirme a instância que você está encerrando para evitar parar outra instância por engano.
  2. Pare a replicação se você for desligar um escravo mysql> STOP SLAVE;.
  3. Lave as páginas sujas com antecedência para reduzir o tempo de desligamento mysql> SET GLOBAL innodb_max_dirty_pages_pct = 0;.
  4. Verifique as consultas demoradas mysql> SHOW PROCESSLIST;, mate-as mysql> kill thread_id;ou aguarde até que elas terminem.
  5. Despejar o buffer pool no desligamento mysql> SET GLOBAL innodb_buffer_pool_dump_at_shutdown = ON;e recarregá-lo na inicialização # vi /etc/my.cnf innodb_buffer_pool_load_at_startup = ON para aquecer o buffer pool.

Depois de confirmar os pontos anteriores, você pode reiniciar o MySQL com segurança shell$ service mysql restart

Para mais detalhes, veja o meu post. Verifique-os antes de desligar o MySQL!

Moll
fonte
Por que isso foi prejudicado? Não sei o suficiente para reconhecer quais comandos são ruins, mas quero saber para que eu possa evitá-los.
27417 Jon
Não sei se o acima é um mau comando. Estou seguindo os passos acima e muitas pessoas fazem. Somente a etapa 4 deve ser cautelosa; você não deve interromper nenhuma consulta até ter certeza do que está fazendo; caso contrário, aguarde até que as consultas de execução longa terminem. Experimente e, se isso o ajudou, faça um voto positivo, caso contrário, faça um voto negativo!
Moll