Encontrei um novo problema ontem com um dos meus bancos de dados escravos MySQL 5.5 que são executados no EC2 na AWS. O banco de dados foi criado a partir de um snapshot de outro escravo. Os dados estão corretos, mas para pelo menos uma tabela um índice secundário está retornando resultados incompletos. Consultar uma tabela filho pelo id pai estava retornando 498 linhas quando deveria ter retornado 504. Consultar as 6 linhas ausentes pela chave primária funcionou e o id pai correto foi retornado, então o problema é com o índice secundário.
Este problema é altamente preocupante para mim, pois, presumivelmente, mesmo que todos os dados no escravo correspondam ao mestre, ainda obterei resultados incorretos de algumas consultas executadas no escravo.
Minha solução de força bruta foi reconstruir a tabela inteira assim:
alter table my_table engine = innodb;
Isso resolveu o problema dessa tabela específica, mas fico com as seguintes perguntas:
1) How can I determine if other tables have similar index corruption?
2) What's the most efficient way to fix the corrupt indexes?
Encontrei alguns bons recursos online para encontrar e corrigir a corrupção de dados do InnoDB, mas não encontrei nada relevante para a corrupção do índice do InnoDB.
Eu olhei no log de erros do MySQL e não encontrei uma arma fumegante. Eu encontrei alguns erros preocupantes do InnoDB. Estou assumindo que este é um problema separado, mas pode estar relacionado:
130109 9:46:41 InnoDB: unable to find a record to delete-mark
InnoDB: tuple DATA TUPLE: 2 fields;
0: len 4; hex 04af1f21; asc !;;
1: len 4; hex 0a1c03bd; asc ;;
InnoDB: record PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 4; hex 04af1f21; asc !;;
1: len 4; hex 0a052a77; asc *w;;
Obrigado Rolando e Michael por suas respostas.
Para fechar o ciclo, aqui está a resposta que encontrei para minhas perguntas originais:
R: Usar
CHECK TABLE
. Eu corrimysqlcheck -c
em todas as tabelas relevantes do InnoDB para descobrir quais tinham corrupção de índiceP: Qual é a maneira mais eficiente de corrigir os índices corrompidos?
OPTIMIZE TABLE
para reconstruir a tabela InnoDB que tem índices corrompidos. Isso causa uma reconstrução completa da tabela que corrige a corrupção.Você pode ter a solução mais fácil que existe. No entanto, gostaria de esclarecer algumas coisas:
Fazer um snapshot com uma instância do MySQL em execução pode afetar o único arquivo responsável pela manipulação de índice secundário: ibdata1.
O tablespace do sistema
ibdata1
é o lar de 7 classes de informações do InnoDBAs classes principais com as quais eu me preocuparia são o Double Write Buffer e o Insert Buffer. Fazer um instantâneo ao vivo com qualquer um deles não escrito corretamente introduzirá corrupção de dados.
Fazer
FLUSH TABLES WITH READ LOCK;
não interrompe as gravações em ibdata1 como se poderia pensar. Já escrevi sobre esse assunto antes . Eu costumava pensar que sim, até que foi apontado pelo colega membro do DBA.SE @ShlomiNoach .Pense no pool de buffers do InnoDB. Você teria que liberar todas as páginas sujas dele para obter tudo desativado no disco. O seguinte força a saída de todas as páginas sujas por tabela:
SET GLOBAL innodb_fast_shutdown = 0;
Seguido porservice mysql stop
SET GLOBAL innodb_max_dirty_pages_pct = 0;
e espere até que 1% do Buffer Pool esteja sujoAlém disso, não se esqueça de que os logs binários e os logs de retransmissão dependem do sistema operacional para liberação.
Um instantâneo do EC2 não é compatível com MySQL nesses aspectos, não mais do que um instantâneo do LVM seria. É por isso que softwares de backup como o R1Soft da CDP possuem um módulo MySQL para essas ocasiões.
Por outro lado, uma instância MYSQL do Amazon RDS está ciente e criada para esses cenários centrados em InnoDb. Somente se houver tabelas MyISAM ativas na Instância RDS seria
FLUSH TABLES WITH READ LOCK;
um mal necessário para executar manualmente .Em relação à sua pergunta original, quando você executou,
ALTER TABLE my_table ENGINE=InnoDB;
você simplesmente reconstruiu as páginas de índice lendo as páginas de dados da tabela, provavelmente ignorando o buffer de inserção ibdata1. É por isso que funcionou para você.Se você puder fazer um mysqldump com
--single-transaction --master-data=1
o Master, scp o mysqldump para o slave, e fazê-lo sem Encargos Financeiros, seria um método mais seguro para configurar o EC2 Slave.Se você precisar fazer o instantâneo, faça isso no Slave:
SET GLOBAL innodb_fast_shutdown = 0;
service mysql stop
service mysql start
/etc/my.cnf
Informações Adicionais: Quanto menores forem ib_logilfe0 e ib_logfile1, mais rápido será o encerramento.
Espero que isso explique muito.
ATUALIZAÇÃO 2013-01-14 10:36 EDT
Você perguntou recentemente na seção de comentários
Tenha em mente que você está usando EC2 e não RDS. Com o RDS, a Amazon é responsável pelo estado holístico da VM e da instância MySQL. Com o EC2, a Amazon é responsável apenas pela VM. O estado holístico da instância MySQL agora está com você. Você pode querer portar o banco de dados para o RDS porque ele vem com os sinos e assobios adicionais para se proteger contra tal corrupção.
Use o comando abaixo e você ficará feliz como estou agora.
Tenho certeza de que você sabe que deve alterar as maiúsculas com suas preferências de armazenamento, não é? :)