Como um SELECT COUNT(*) no LiveZilla derrubou o MySQL por max_connections (e como mitiguei)
Voltar para blog

Como um SELECT COUNT(*) no LiveZilla derrubou o MySQL por max_connections (e como mitiguei)

10/09/2026 · 3 min · Banco de Dados

Quem mantém sites e servidores em produção sabe o susto que dá receber um alerta de banco de dados fora do ar. Recentemente, investiguei um incidente clássico de exaustão de conexões no MySQL/MariaDB que mostra perfeitamente como uma aplicação legada sem manutenção pode derrubar o servidor inteiro.

Abaixo, documento o diagnóstico no terminal, o comando em lote para limpar os processos travados e as recomendações práticas para evitar a reincidência.


O sintoma inicial: erro de max_connections#

O alerta disparou indicando que o MySQL havia parado de responder a novas conexões. Ao verificar os logs, o erro clássico apareceu:

ERROR 1040 (08004): Too many connections

Quando o número de conexões ativas bate no teto global configurado no banco (@@max_connections), qualquer nova tentativa de conexão (vinda dos pools do PHP-FPM ou de outros sites) é recusada na hora.


Investigando o terminal: isolando a query ofensora#

Acessei o terminal para verificar o que estava rodando no banco de dados via processlist:

| ID       | User            | Host      | db              | Command | Time | State        | Info                                                                                                   |
| 55764331 | cliente_liveusr | localhost | cliente_livechat| Query   | 5054 | Sending data | SELECT COUNT(*) AS `total`,(SELECT COUNT(*) FROM (SELECT `lz_chat_archive`.`chat_id` FROM `lz_chat_a |
| 55767542 | cliente_liveusr | localhost | cliente_livechat| Query   | 5024 | Sending data | SELECT COUNT(*) AS `total`,(SELECT COUNT(*) FROM (SELECT `lz_chat_archive`.`chat_id` FROM `lz_chat_a |
| 55769351 | cliente_liveusr | localhost | cliente_livechat| Query   | 5025 | Sending data | SELECT COUNT(*) AS `total`,(SELECT COUNT(*) FROM (SELECT `lz_chat_archive`.`chat_id` FROM `lz_chat_a |

O que o diagnóstico revelou:#

O mecanismo da falha#

O LiveZilla tentava gerar estatísticas de atendimentos em tempo real no painel. Como a tabela lz_chat_archive tinha centenas de milhares de linhas e não possuía índices apropriados para aquela consulta, o MySQL criava tabelas temporárias no disco a cada clique.

A cada requisição web, o PHP abria uma nova conexão e disparava o mesmo SELECT COUNT(*). Como as consultas anteriores nunca terminavam, as novas foram se acumulando até bater no teto de conexões do MySQL, derrubando o banco para todas as aplicações do servidor.


Ação emergencial: matando conexões travadas em lote#

Com dezenas de threads travadas há milhares de segundos, dar KILL manual processo por processo via terminal demoraria demais.

Para expurgar todas as conexões presas do usuário específico de forma rápida e segura:

mysql -e "SELECT concat('KILL ', id, ';') FROM information_schema.processlist WHERE user = 'cliente_liveusr' AND time > 100" | grep -v "concat" | mysql

Como esse comando funciona:#

  1. Consulta a tabela information_schema.processlist buscando apenas threads daquele usuário com tempo superior a 100 segundos.
  2. Monta a instrução KILL [ID]; para cada registro.
  3. O grep -v "concat" remove o cabeçalho gerado pelo MySQL.
  4. O resultado é jogado de volta no próprio cliente mysql, executando todos os encerramentos em um único lote.

Dica complementar: Se o pool do PHP-FPM continuar enviando novas conexões imediatamente após a limpeza, vale reiniciar os workers daquele usuário para cortar os sockets residuais (apenas se a conta for dedicada exclusivamente ao LiveZilla; caso contrário, reinicie apenas o pool específico ou via systemctl restart php8.x-fpm para não interromper outros sites do usuário):

killall -u cliente_liveusr php-fpm

Conclusão: recomendações práticas para resolver em definitivo#

  1. Expurgo e arquivamento: Limpar registros antigos da tabela lz_chat_archive ou exportar históricos com mais de 1 ano para armazenamento frio.
  2. Revisão de índices: Criar índices na coluna chat_id e em colunas de datas utilizadas nos filtros estatísticos.
  3. Desativação de estatísticas em tempo real: Configurar o painel do chat para atualizar relatórios com intervalos maiores ou sob demanda.
  4. Por que apenas aumentar o max_connections é perigoso: Aumentar o limite sem corrigir a query apenas faz com que centenas de consultas pesadas fiquem rodando simultaneamente na memória RAM, o que pode invocar o OOM Killer do kernel Linux e derrubar o servidor por falta de memória física.

Este artigo foi útil?

Deixe uma reação rápida para apoiar o conteúdo:

CC BY-NC

Este post está licenciado sob CC BY-NC.

Comentários

Participe da discussão abaixo.

0 comentários