Temos uma instância MySQL que na maioria das vezes funciona bem. De tempos em tempos, porém, observamos um comportamento estranho. O que acontece é que, de repente, as conexões do MySQL atingem o limite (atualmente definido como 1000) e o MySQL praticamente para. O seguinte é observado quando verificamos os gráficos para este servidor:
A imagem é de uma instância do Grafana que executa um exportador MySQL. O que me incomoda é porque os threads do cache não são reutilizados. A outra questão é por que os threads no cache de repente caem para zero, mas ao mesmo tempo nenhum novo thread é criado (de acordo com o segundo gráfico - a linha azul permanece em 0).
Por fim, meu objetivo é entender por que 1000 conexões são usadas de repente e se isso é um problema com o MySQL ou o aplicativo. Isto é o que os documentos do MySQL dizem em relação aos threads:
Quantos threads o servidor deve armazenar em cache para reutilização. Quando um cliente se desconecta, os encadeamentos do cliente são colocados no cache se houver menos de encadeamentos thread_cache_size lá. As solicitações de encadeamentos são atendidas reutilizando encadeamentos retirados do cache, se possível, e somente quando o cache está vazio é criado um novo encadeamento.
Qualquer ajuda ou orientação será muito apreciada!
Rebanho trovejante. Ou, tantas pessoas em uma mercearia que ninguém pode mover seu carrinho.
Quando
Threads_running
é 349, cada um deles está esperando e esperando e esperando por uma pequena fatia de CPU e uma pequena quantidade de E/S e... O efeito é que todos demoram uma eternidade para terminar. Enquanto isso, outros que tentam entrar são permitidos porque você tem uma altamax_connections
, etc.Mas isso não explica o que empurrou o rebanho para o penhasco. Pode ser algo tão trivial quanto um grande
SELECT
que bloqueia o que o rebanho normalmente faz.Você está com o slowlog ativado? Com um valor baixo de
long_query_time
? Nesse caso, você já pode ter a resposta no slowlog. Como você não entrou em pânico e reiniciou, esse Select lento (se realmente existir) estará no slowlog. Com base nos gráficos, acho que pode ter um tempo de 80 a 110 segundos.Quanto ao mergulho em
Threads_cached
, isso fica um pouco complexo. Primeiro, deixe-me explicar as partes sem mergulho. Antes do 'evento' foram feitas cerca de 200 ligações; cada um durou o suficiente para que houvesse 200 'estáveis' conectados.Após o evento, havia tantos esperando para entrar que elevou o número para cerca de 350.
Ter
thread_cache_size = 500
desperdiça memória; sugiro que reduza para 250.Quanto ao mergulho, vou fazer algumas suposições. Tantas conexões estavam se esforçando tanto para fazer as coisas que novas conexões tiveram o acesso negado. (Isso pode ser deliberado por parte do MySQL, ou pode ser um efeito colateral de todo mundo tentando vários mutexes.)
Também é imprudente ter
max_connections = 1000
; isso apenas convida a cenários como este. Em vez disso, faça com que os clientes 'aceitem o calor' quando algo soluça - ao ter o acesso negado ao MySQL. Além disso, isso torna mais fácil dizer "Opa, estamos tendo um problema, por favor aguarde, e por favor não pressione Enviar novamente, nem Atualizar!" Ou simplesmente dê um "500".Resumindo: acho que o slowlog pode apontar para a causa do evento.