Encontramos um problema depois de 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. (Eu ouvi falar do uso do InnoDB em vez do MyISAM, mas não podemos mudar o mecanismo em um futuro próximo).
Poderíamos identificá-lo para uma consulta de atualização que é executada 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 está definido) - os arquivos em cache da página são excluídos
Nesse ponto, a página inteira fica lenta. O próprio banco de dados está ocupado por minutos. 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 no nível da tabela .
1. Não entendo por que essa atualização na tabela article_comments
pode afetar as instruções de seleção da tabela article
para aguardar o bloqueio no nível da tabela. Na lista de processos, quase todas as consultas em espera eram desta tabela. Eu li sobre o fato de que as atualizações / inserções são preferíveis às seleções e que isso pode causar esses problemas, mas a tabela de artigos em si não é atualizada quando os comentários são ativados, portanto as seleções não devem esperar. Eu não sabia disso?
2. Existe algo além de mudar para o InnoDB para evitar esse comportamento ou pelo menos para obter um melhor equilíbrio? 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 incorreta, mas não sei como identificar.
key_buffer_size
foi definido como1GB
. Aumentar isso para10GB
reduzir o problema.Respostas:
O MyISAM Storage Engine é furiosamente notório por executar bloqueios de tabela completos para qualquer DML (INSERTs, UPDATEs, DELETEs). O InnoDB definitivamente resolveria esse problema a longo prazo.
Escrevi sobre prós e contras do uso do 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
possui um ou mais índices comstatus
uma colunaarticle_comments
são armazenadas em cache no MyISAM Key Buffer (dimensionado por key_buffer_size ), fazendo com que páginas de índice antigas saiam do MyISAM Key Bufferarticle
earticle_comments
No meu cenário sugerido, os SELECTs contra a
article
tabela podem ser impedidos de permitir gravações, pois precisam aguardararticle_comments
a liberação de qualquer DML (nesse caso, umUPDATE
)fonte
Cheira como você tem 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 especificada são eliminadas quando qualquer gravação ocorre nessa tabela. Quanto maior o CQ, mais lenta é essa tarefa.
O MyISAM usa bloqueios "no nível da tabela". Leituras e gravações não podem ocorrer ao mesmo tempo (na mesma tabela). Bruto, mas eficaz.
fonte