Temos um servidor escravo que interrompeu a replicação devido ao seguinte erro:
Slave SQL: Query caused different errors on master and slave.
Qual poderia ser a causa desse erro? E qual seria uma maneira de consertar isso?
A versão do mestre e do escravo é MySQL 5.5.30
130726 23:55:45 [Note] C:\Program Files\MySQL\MySQL Server 5.5\bin\mysqld: Shutdown complete
130726 23:58:39 [Note] Plugin 'FEDERATED' is disabled.
130726 23:58:39 [Warning] C:\Program Files\MySQL\MySQL Server 5.5\bin\mysqld: ignoring option '--innodb-file-per-table' due to invalid value 'ON'
130726 23:58:39 [Note] Plugin 'InnoDB' is disabled.
130726 23:58:39 [Note] Server hostname (bind-address): '0.0.0.0'; port: 3306
130726 23:58:39 [Note] - '0.0.0.0' resolves to '0.0.0.0';
130726 23:58:39 [Note] Server socket created on IP: '0.0.0.0'.
130726 23:58:39 [Note] Slave SQL thread initialized, starting replication
in log 'mysql-bin.000234' at position 1065421256,
relay log '.\slave-relay-bin.000917' position: 1065421402
130726 23:58:39 [Note] Slave I/O thread: connected to master '[email protected]:3306',
replication started in log 'mysql-bin.000235' at position 166680598
130726 23:58:39 [Note] Event Scheduler: Loaded 0 events
130726 23:58:39 [Note] C:\Program Files\MySQL\MySQL Server 5.5\bin\mysqld:
ready for connections.
Version: '5.5.30-log' socket: '' port: 3306 MySQL Community Server (GPL)
130726 23:59:04 [ERROR] Slave SQL: Query caused different errors on master and slave.
Error on master: message (format)='Incorrect key file for table '%-.200s';
try to repair it' error code=1034 ;
Error on slave: actual message='no error', error code=0.
Default database: 'shared'.
Query: 'CREATE TEMPORARY TABLE tmp_grades (
vehsysid INT(11),
grade INT(1),
dt TIMESTAMP,
INDEX(vehsysid),
INDEX(grade),
INDEX(dt)
) SELECT vehsysid, Grade, MAX(dt) AS dt
FROM shared.tbl_valuations
GROUP BY vehsysid, grade', Error_code: 0
130726 23:59:04 [ERROR] Error running query, slave SQL thread aborted. Fix the problem,
and restart the slave SQL thread with "SLAVE START".
We stopped at log 'mysql-bin.000234' position 1065421256
O que mais não consigo descobrir é como uma tabela temporária levaria a esse erro (no mestre):
'Incorrect key file for table '%-.200s'; try to repair it' error code=1034
As últimas linhas do log de erros mestre:
130725 23:15:57 [Warning] Warning: Enabling keys got errno 120 on shared.tmp_grades, retrying
130726 23:15:58 [Warning] Warning: Enabling keys got errno 137 on shared.tmp_grades, retrying
Informação adicional:
- tanto o Master quanto o Slave rodam no Windows (não sei se isso é relevante).
- os discos em ambos têm muito espaço.
- formato de replicação é
MIXED
- innodb é ignorado em todas as instâncias, master e slaves. MyISAM é o padrão.
Suspeito que parte disso esteja afirmando o óbvio. Peço desculpas por isso, mas queria incluí-lo no interesse da meticulosidade.
A parada do escravo nesta condição é o comportamento esperado.
Cada consulta que é gravada no binlog tem metadados que incluem o código de erro que a consulta retornou no servidor que gerou o evento binlog. O código de erro é normalmente 0 para "sem erro". Você pode ver esse código de erro e os outros metadados se executar o log por meio de
mysqlbinlog
.Se ocorrer um erro após a consulta atingir um determinado ponto na execução, a consulta ainda será gravada no log binário junto com o código de erro.
O escravo espera encontrar o mesmo erro que o mestre encontrou (geralmente, mas nem sempre 0) e para quando os valores não correspondem para ajudar a evitar inconsistências de dados que poderiam resultar se a replicação pudesse continuar depois que tal condição fosse encontrada.
As estruturas de dados binlog não parecem ter um lugar para a mensagem de erro ou os valores que foram sprintf ()'ed na mensagem - apenas o código - então o escravo tem que traduzir esse código em algo legível por humanos. Sem os valores que o mestre teria conectado à mensagem, ele apenas exibe o formato bruto da mensagem, incluindo os espaços reservados.
Portanto, o que você está vendo como o último erro de replicação no escravo é um comportamento normal quando ocorre um erro no mestre, mas a mesma consulta não gera um erro no escravo.
Você pode ignorar o erro
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; START SLAVE;
como provavelmente já fez até agora, mas a recuperação além disso depende do que você fez com os resultados dessa tabela temporária. Se a tabela temporária foi criada e preenchida por um único evento baseado em instrução e não foi usada para fazer nenhum tipo de atualização adicional da tabela, você pode estar bem, porque a replicação normalmente ignora erros que ocorrem ao tentarDROP TEMPORARY TABLE
e a tabela temporária não 't exist on the slave, já que a thread slave não tem uma maneira confiável de saber se aCREATE TEMPORARY TABLE
instrução realmente apareceu anteriormente no log binário ou se o slave pode ter parado e começado entre oCREATE
eDROP
eventos na tabela temporária (o que teria destruído quaisquer tabelas temporárias que tivessem sido criadas pelo encadeamento SQL escravo antes da parada/início). Por outro lado, se a tabela temporária foi usada para atualizar outras tabelas, você ainda pode estar bem porque essas atualizações podem ter sido escritas como eventos baseados em linha, já que você está noMIXED
formato binlog ... mas eu verificaria a consistência entre qualquer tabelas que você atualizou a partir dos resultados da tabela temporária, se houver.Quanto aos erros que ocorreram no master:
Há algo que eu perdi no começo - pensei que eles estavam separados por 1 segundo, mas esses erros realmente parecem ter ocorrido em dois dias diferentes, 25 e 26, então 24 horas e 1 segundo separados ... 2 avisos diferentes no mesmo nome de tabela temporária, mas na verdade duas tabelas temporárias diferentes geradas com um dia de intervalo.
A princípio achei estranho que você não tivesse mensagens de "Arquivo de chave incorreto" no log do mestre, mas essas não estariam no log -- seriam erros retornados ao cliente que emitiu a consulta.
Lembro-me de ter visto erros como esse nos logs de erros dos meus servidores, mas, pelo que posso dizer, esses erros "Arquivo de chave incorreto" só vão para o log de erros do servidor se forem encontrados pelo encadeamento slave_sql ou por um consulta executada pelo agendador de eventos, pois são as únicas vezes que não há uma conexão do cliente para receber o erro... então pode ser que o que está executando a consulta que cria a tabela temporária tenha gerado um log de erros que podem ser de interesse.
Não podemos presumir tecnicamente que foi a tabela 'tmp_grades' que encontrou o erro "Arquivo de chave incorreto" se a
SELECT
parte da consulta criou sua própria tabela temporária implícita... poderia ter sido essa tabela, causando um erro que afetou a consulta.Olhando um pouco para dentro, parece que quando você cria uma
MyISAM
tabela temporária com índices em umaCREATE TEMPORARY TABLE ... SELECT
instrução, a tabela é criada com os índices desativados e, em seguida, o servidor cria e ativa os índices depois que os dados são gravados, em vez de atualizar índices à medida que insere dados... e parece que os avisos que você está vendo podem ter sido no momento em que ele cria os índices ("Ativando chaves...")... e supondo que esteja correto, sugere apenas um um punhado de possibilidades, listadas em nenhuma ordem específica, mas todas giram em torno da ideia de que sua tabela temporária está sendo corrompida:Using temporary
), então você tem uma condição transitória de pouco espaço em disco que desaparece imediatamente após o término do outro trabalhoSELECT
parte da consulta que está preenchendo a tabela temporária está construindo outra tabela temporária implícita que está causando uma condição transitória de pouco espaço em disco e competindo com a tabela explícita por espaçoClaro, o maior problema aqui é que nenhuma dessas explicações parece particularmente provável. Depois de verificar se os dados entre as duas máquinas estão consistentes no momento, a próxima etapa infeliz pode ser esperar que isso aconteça novamente, embora eu esteja inclinado a verificar a memória do sistema e a integridade do disco temporário se fosse eu.
como Michael disse "Você tem um problema com a memória do sistema, então a tabela temporária está sendo corrompida no cache do sistema operacional" este é o status mais comum, tente aumentar tmp_table_size e max_heap_table_size, pois a instrução tem "criar tabela temporária" e "grupo por" cláusulas que usam tabela temporária que precisa desses buffers, minha sugestão é: aumente esses buffers no mestre e no escravo, você pode encontrar mais detalhes neste link http://dev.mysql.com/doc/refman/5.0/en/server- system-variables.html#sysvar_tmp_table_size