quinta-feira, 4 de dezembro de 2014

MySQL - SQL thread is not running?



Imagine o seguinte cenário, você tem um MySQL master e um slave configurado com replicação assíncrona. Por alguma razão você descobre através da consulta de status do slave que o SQL thread parou de funcionar, mas o IO thread continua em execução buscando logs do master. 

COMO IDENTIFICAR A CAUSA DO PROBLEMA? 

        - Verifique o log de erro do MySQL, lá constará o código de erro gerado durante o processo de replicação, seja ela por row ou statement, e este código já lhe ajudará a buscar soluções na documentação. 

        - No mesmo log você poderá verificar qual a posição e binlog do master em que ocorreu o erro, isso será muito útil no futuro. 

        Consideraremos aqui neste exemplo que o erro foi causado por um SQL que violou uma CONSTRAINT de PK ou FK.

        O ERRO É DE VIOLAÇÃO E AGORA? 

 1 - Primeiramente utilizando o mysqlbinlog acesse o log binário do master indicado no erro do MySQL do slave e com o -j informe a posição;
2 - Ao identificar o STATEMENT ou ROW que foi executado/alterada você poderá acessar o MySQL master e comparar os dados da tabela alvo com a do slave;
3 - Aqui é certo que você identificará diferenças de integridade entre as tabelas, pois lembre que o slave está atrasado com relação ao master;
4 - Pule uma posição no log do master no slave: 

CHANGE MASTER TO MASTER_LOG_FILE = '$master_log_name' MASTER_LOG_POS = $master_log_pos+1; 

Viu agora o porquê da importância da posição do log lido no master? Onde $master_log_name e $master_log_pos podem ser obtidos ao consultar o status do slave

 5 - Feito isto ative o slave novamente:
     
START SLAVE;

Se nenhum outro erro ocorreu após o slave se atualizar em relação ao master(veja no status do slave) então é hora de verificar como ficaram os dados da tabela que apresentou o erro. COMO? 

        Se seu slave não tem delay setado e o fluxo de alterações e inserções da tabela não é constante podes realizar a validação por MD5SUM. COMO? 
mysql > \P md5sum 
mysql > select * from tabela_alvo; (não faça isso em tabelas gigantes!)
O resultado no master e slave devem ser o mesmo valor de md5. Para normalizar o client basta executar \P. 

Bom, se ainda assim tem diferenças na tabela alvo, considere ajustar os dados dela via dump com a function slave parada, ou ressincronizar o slave.