Encontramos um problema após mover o banco de dados de nosso cliente para um servidor extra. Isso deveria ter tido efeitos positivos no desempenho do site, mas há um problema com o bloqueio de tabelas no MyISAM. (Já ouvi falar do uso do InnoDB em vez do MyISAM, mas não podemos alterar o mecanismo em um futuro próximo).
Podemos identificá-lo em uma consulta de atualização que é realizada quando um moderador ativa um comentário no site de artigos. Este é o processo:
- a consulta de atualização é processada
SET status = 1 WHERE id = 5
(o índice é definido) - os arquivos em cache da página são excluídos
Neste ponto, a página inteira fica lenta. O próprio banco de dados está ocupado por minutos. Eu busquei a lista de processos algumas vezes e vi cerca de 60 entradas de diferentes consultas de seleção, que estavam todas no estado aguardando o bloqueio de nível de tabela .
1. Não entendo por que essa atualização na tabela article_comments
pode afetar as instruções select para que article
a tabela aguarde o bloqueio no nível da tabela. Na processlist quase todas as consultas em espera eram desta tabela. Eu li sobre o fato de que atualizações/inserções são preferidas a seleções e que isso pode causar tais problemas, mas a tabela de artigos em si não é atualizada quando os comentários são ativados, então as seleções não devem esperar. Eu entendi errado isso?
2. Existe algo além de mudar para o InnoDB para evitar esse comportamento ou pelo menos para obter um equilíbrio melhor? Estou muito irritado com o fato de que esse problema não apareceu antes de mover o banco de dados para o novo servidor. Acho que há alguma configuração errada, mas não sei como identificar.
O MyISAM Storage Engine é furiosamente notório por realizar bloqueios de tabela completos para qualquer DML (INSERTs, UPDATEs, DELETEs). O InnoDB definitivamente resolveria esse problema a longo prazo.
Eu escrevi sobre prós e contras de usar MyISAM vs InnoDB
Com relação à sua pergunta atual, aqui está um cenário possível:
article
earticle_comments
são ambas tabelas MyISAMarticle_comments
tem um ou mais índices comstatus
como uma colunaarticle_comments
são armazenadas em cache no MyISAM Key Buffer (dimensionado por key_buffer_size ), fazendo com que as páginas de índice antigas saiam do MyISAM Key Bufferarticle
earticle_comments
No meu cenário sugerido, SELECTs na
article
tabela podem ser impedidos de permitir gravações por causa de ter que esperar paraarticle_comments
estar livre de qualquer DML (neste caso, umUPDATE
)Cheira como se você tivesse um grande Query_cache?
Para sistemas de produção com muitas gravações, você também pode desativar o query_cache.
Todas as entradas no query_cache para a tabela fornecida são limpas quando ocorre qualquer gravação nessa tabela. Quanto maior o QC, mais lenta é essa tarefa.
MyISAM usa bloqueios de "nível de tabela". Leituras e gravações não podem ocorrer ao mesmo tempo (na mesma tabela). Bruto, mas eficaz.