O esgotamento de conexões com o banco de dados no PHP costuma se manifestar como erros intermitentes: algumas solicitações falham, outras ficam aguardando e o problema piora em períodos de alta carga. Aumentar o limite de conexões pode aliviar o problema, mas também pode transferir a saturação para o servidor de banco de dados. A solução começa por identificar qual recurso está se esgotando e quem mantém as conexões ocupadas.
Reconheça os sintomas e delimite a falha

Procure erros como «too many connections», falhas ao abrir uma conexão, tempos limite excedidos ou solicitações que ultrapassam o tempo máximo de execução. Compare a frequência desses erros com o tráfego e com outros indicadores: latência da aplicação, uso de CPU e memória, erros do banco de dados e duração das solicitações.
A diferença entre carga alta e baixa oferece uma primeira pista. Se os erros aparecem durante picos e desaparecem quando o tráfego diminui, pode haver um limite de concorrência. Se persistirem com poucas solicitações, investigue conexões retidas, processos bloqueados, consultas prolongadas ou um banco de dados inacessível. Confirme também se outros serviços compartilham o mesmo limite: o PHP não é necessariamente o único consumidor.
Diferencie conexões esgotadas de consultas lentas e bloqueios
São problemas relacionados, mas não equivalentes. O esgotamento de conexões ocorre quando não há capacidade disponível para abrir outra. Uma consulta lenta ocupa uma conexão por mais tempo e pode provocar o esgotamento à medida que se acumulam. Um bloqueio faz uma consulta esperar até que outra transação libere recursos. A indisponibilidade significa que o banco de dados não consegue aceitar ou atender conexões por uma causa mais ampla.
Examine a mensagem e o ponto da falha. Se a solicitação falhar antes de executar uma consulta, verifique a criação de conexões e o limite atingido. Se conseguir se conectar e depois demorar, inspecione as consultas em andamento, seus tempos, esperas e transações abertas. Não conclua que «faltam conexões» apenas porque a aplicação responde devagar: aumentar a capacidade não corrige uma consulta dispendiosa nem um bloqueio.
Relacione a concorrência do PHP ao limite do banco de dados
No modelo habitual do PHP, em que processos atendem às solicitações, cada processo pode precisar de uma conexão enquanto executa operações no banco de dados. A demanda potencial depende de quantos processos podem operar simultaneamente, de quantas conexões cada um abre e de quanto tempo as mantém. Também é preciso contabilizar as conexões de tarefas em segundo plano, comandos de console e outros serviços.
Faça uma estimativa conservadora do pior caso: multiplique a concorrência máxima efetiva de cada grupo de processos pelo número de conexões simultâneas que cada processo pode usar e some os consumidores que compartilham o banco de dados. Compare o resultado com o limite configurado e reserve uma margem para operações administrativas e variações de carga. Não suponha que cada solicitação sempre corresponda a uma conexão: o ciclo de vida depende do cliente de banco de dados, da configuração e do padrão de uso.
Verifique também como a carga é distribuída. Várias instâncias do PHP podem respeitar seus limites locais e, ainda assim, exceder em conjunto a capacidade do banco de dados. O escalonamento horizontal aumenta a concorrência potencial; não é uma medida segura de mitigação se o total de conexões não for recalculado.
Meça pelos dois lados
Correlacione as métricas da aplicação e do banco de dados usando timestamps. No PHP, registre a duração das solicitações, os erros de conexão, os tempos limite e o número de processos ocupados. No banco de dados, verifique as conexões ativas e máximas, as rejeições, as consultas em execução, o tempo de existência das sessões e as esperas disponíveis no mecanismo.
Evite registrar credenciais, strings de conexão completas ou dados confidenciais das consultas. Se o mecanismo permitir identificar sessões e estados, use essas informações para distinguir uma conexão inativa de uma consulta ativa ou de uma transação pendente. Compare os registros dos dois lados: um pico de conexões simultâneo a processos PHP ocupados aponta para concorrência; muitas sessões antigas ou processos inativos sugerem retenção; algumas consultas de longa duração podem explicar por que a capacidade é consumida aos poucos.
A instrumentação deve permitir responder a três perguntas: quantas conexões estão em uso, quanto tempo duram e que trabalho as mantém ocupadas. Sem essa linha do tempo, alterar limites ou ativar conexões persistentes introduz mais variáveis e dificulta encontrar a causa.
Avalie conexões persistentes e de longa duração
Uma conexão persistente pode reduzir o custo de abrir conexões repetidamente, especialmente quando o ambiente mantém processos entre solicitações. No entanto, uma conexão que permanece associada a um processo também pode ocupar uma vaga mesmo sem executar consultas. Se houver muitos processos ou várias instâncias, o conjunto de conexões retidas pode atingir o limite do banco de dados.
Verifique o ciclo de vida real do processo e do driver antes de ativar ou desativar conexões persistentes. Confirme como a sessão é reutilizada e se a aplicação restabelece o estado esperado entre solicitações, como transações, variáveis de sessão ou configurações específicas da conexão. Conexões persistentes não são um pool universal nem garantem menor consumo; teste-as sob carga representativa e observe o número máximo de conexões, a latência e o estado residual.
Mitigue em etapas e com base em evidências
- Limite a concorrência. Ajuste os processos do PHP ou o paralelismo dos workers para que a demanda simultânea seja compatível com a capacidade compartilhada. Isso reduz a pressão, mas pode aumentar a fila e a latência se a capacidade ficar abaixo da demanda sustentada.
- Libere recursos quando não forem mais necessários. Feche conexões explicitamente se a biblioteca e o padrão de execução permitirem, e evite mantê-las durante operações que não envolvam o banco de dados. Lembre-se de que fechar uma conexão persistente não necessariamente libera a conexão física do servidor: o resultado depende do driver e do ciclo de vida do processo. Verifique se há transações que permanecem abertas e caminhos de erro que não concluem a limpeza.
- Reduza o tempo de ocupação. Analise consultas lentas, índices, volume de resultados e transações. Otimizar uma operação que mantém uma conexão ocupada por muito tempo pode reduzir a demanda simultânea sem elevar o limite.
- Ajuste os limites somente após medir. Aumentar o máximo pode ser razoável se houver capacidade de CPU e memória no banco de dados e se o novo pior caso for sustentável. Caso contrário, isso permite que mais trabalho se acumule e agrava a saturação.
Aplique uma alteração de cada vez, registre o estado anterior e defina uma condição de reversão. Se o sistema já estiver afetado, reduzir temporariamente a concorrência pode ser mais seguro do que reiniciar todos os processos de uma só vez, o que poderia criar um novo pico de conexões.
Quando considerar um pool ou proxy de conexões
Um pool ou proxy pode reutilizar conexões físicas e controlar quantas chegam ao mecanismo, o que é útil quando há muitos processos de aplicação com conexões de curta duração. Isso não elimina o trabalho simultâneo nem torna as consultas mais rápidas; introduz outra camada, com capacidade, filas, limites e modos de operação próprios.
Antes de adotá-lo, verifique a compatibilidade com o mecanismo, o driver PHP, a autenticação, o uso de transações e o estado da sessão. Analise como ele gerencia conexões longas, reconexões e falhas do proxy, e defina métricas e procedimentos para operá-lo. Valide-o com testes que representem a concorrência real: uma configuração que funciona em desenvolvimento pode se comportar de outra forma sob pressão.
Prepare a recuperação e evite recorrências

Configure alertas para conexões próximas do limite, rejeições, duração das consultas e saturação dos processos PHP. Acrescente um teste de carga representativo que inclua instâncias, tarefas em segundo plano e outros consumidores; verifique o pior caso, não apenas a média. Mantenha um procedimento operacional que indique o que medir, como limitar a concorrência, quem pode alterar a capacidade e quando reverter.
Depois de recuperar o serviço, analise a sequência que precedeu o incidente: mudanças no tráfego, implantações, novas consultas, aumento do número de processos ou falhas de limpeza. O objetivo é estabelecer uma relação de causa e efeito com base em dados. Se as métricas mostrarem conexões retidas, corrija o ciclo de vida delas; se a duração das consultas for o fator dominante, otimize-as; se a concorrência legítima superar a capacidade, dimensione os recursos e limite a concorrência com um orçamento explícito de conexões.



