El error SQLSTATE[HY000] [1040] Too many connections indica que el servidor MySQL o MariaDB ha alcanzado el límite máximo de conexiones concurrentes permitidas. Cuando esto ocurre, Magento 2 no puede abrir una nueva sesión con la base de datos para responder a las solicitudes de los usuarios o del sistema, devolviendo una pantalla de excepción o un error HTTP 500. La solución inmediata consiste en incrementar la variable max_connections en el motor de base de datos y optimizar la gestión de procesos persistentes en el servidor web.
Qué significa el error
El mensaje exacto SQLSTATE[HY000] [1040] Too many connections es una excepción emitida por la capa PDO de PHP cuando la llamada a la base de datos falla en la fase de saludo (handshake). Aparece tanto en el frontal de la tienda online como en el panel de administración de Magento 2. También puede manifestarse durante la ejecución de tareas programadas desde la línea de comandos (CLI). Afecta a cualquier versión de Magento 2 (2.3.x, 2.4.x) ejecutada sobre MySQL 8.0 o MariaDB 10.x cuando el volumen de peticiones entrantes supera la capacidad configurada en el parámetro max_connections del demonio MySQL.
Causas más habituales
- Límite por defecto de MySQL demasiado bajo: El valor predeterminado de
max_connectionssuele ser 151, insuficiente para el tráfico real de Magento 2. - Procesos PHP descontrolados: Un número excesivo de trabajadores en PHP-FPM (
pm.max_children) consumiendo conexiones individuales a la base de datos. - Consultas colgadas o bloqueos en la base de datos: Transacciones lentas o tablas bloqueadas que mantienen abiertas las conexiones durante demasiado tiempo.
- Tareas Cron concurrentes o atascadas: Múltiples ejecuciones del cron de Magento 2 solapándose y abriendo conexiones sin cerrarlas. Si sospechas de este problema, puedes consultar la guía para diagnosticar errores de Cron en Magento.
- Conexiones persistentes en el archivo env.php: Configuración incorrecta del driver de base de datos en Magento utilizando conexiones permanentes no reutilizadas.
- Ataques de bots o tráfico de rastreadores: Picos repentinos de tráfico no almacenado en caché que golpean directamente al backend de Magento.
Antes de empezar
Antes de modificar archivos de configuración en el servidor de producción, asegúrate de cumplir con los siguientes requisitos:
- Acceso con privilegios de root o acceso sudo mediante SSH al servidor.
- Acceso con el usuario root o un usuario administrador a MySQL/MariaDB.
- Realizar una copia de seguridad rápida de los archivos de configuración de MySQL (
my.cnfo50-server.cnf). - Entorno verificado sobre distribuciones Linux como Ubuntu 22.04/24.04 LTS o Debian 11/12 corriendo PHP 8.1/8.2 y Magento 2.4.x.
Solución 1: Aumentar el límite max_connections en MySQL/MariaDB
Esta es la solución más rápida y directa para devolver la operatividad a la tienda. Al aumentar el límite de conexiones, el motor de base de datos aceptará más peticiones simultáneas de PHP.
- Accede a tu servidor mediante SSH.
- Inicia sesión en MySQL con tu usuario administrador:
sudo mysql -u root -p - Comprueba el límite de conexiones actual y el pico de conexiones máximo alcanzado ejecutando:
SHOW VARIABLES LIKE 'max_connections'; SHOW STATUS LIKE 'Max_used_connections'; - Cambia el valor de forma temporal en caliente para restaurar el servicio inmediatamente:
SET GLOBAL max_connections = 500; - Sal de la consola de MySQL tecleando
exit;. - Para hacer que este cambio sea permanente tras un reinicio del servidor, edita el archivo de configuración de MySQL (habitualmente en
/etc/mysql/mysql.conf.d/mysqld.cnfo/etc/my.cnf):sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf - Busca o añade la directiva dentro de la sección
[mysqld]:[mysqld] max_connections = 500 - Guarda el archivo (Ctrl+O, Enter) y sal (Ctrl+X).
Por qué funciona: Modificar este parámetro permite que el hilo principal de MySQL asigne más buffers de conexión por cliente, evitando el rechazo inmediato de peticiones cuando la tienda experimenta picos de visitas.
Solución 2: Ajustar los tiempos de espera de conexiones inactivas (wait_timeout)
Incluso con un número elevado de max_connections, si los hilos quedan abiertos en estado «Sleep» ocuparán slots útiles. Reducir los tiempos de espera libera conexiones no utilizadas mucho más rápido.
- Abre la consola de MySQL:
sudo mysql -u root -p - Verifica los valores actuales de tiempo de espera:
SHOW VARIABLES LIKE '%timeout%'; - Ajusta los parámetros
wait_timeouteinteractive_timeouta valores más razonables (por defecto suelen estar en 28800 segundos, es decir, 8 horas). Aplica 60 segundos temporalmente:SET GLOBAL wait_timeout = 60; SET GLOBAL interactive_timeout = 60; - Añade estos cambios al archivo de configuración
mysqld.cnfpara hacerlos permanentes:[mysqld] wait_timeout = 60 interactive_timeout = 60 - Reinicia el servicio de base de datos para asegurar que se apliquen correctamente los límites de memoria asociados:
sudo systemctl restart mysql
Por qué funciona: Al reducir el tiempo de inactividad permitido, MySQL cierra automáticamente los hilos que hayan completado su consulta pero cuyo proceso PHP no haya enviado la instrucción explícita de desconexión.
Solución 3: Optimizar la configuración de PHP-FPM y el pool de trabajadores
Un error común es asignar demasiados hilos de ejecución en PHP-FPM. Si PHP genera 200 procesos hijo simultáneos y cada uno intenta abrir una conexión a MySQL, se sobrepasará la capacidad del motor aunque hayas ajustado el parámetro previo. Si experimentas problemas derivados de límites a nivel de sistema operativo, consulta también cómo solucionar el error Too Many Open Files en Linux.
- Edita el archivo de configuración del pool de PHP-FPM para Magento (la ruta habitual es
/etc/php/8.2/fpm/pool.d/www.conf):sudo nano /etc/php/8.2/fpm/pool.d/www.conf - Revisa las siguientes directivas y ajusta sus valores según la memoria RAM disponible en tu servidor:
pm = dynamic pm.max_children = 50 pm.start_servers = 10 pm.min_spare_servers = 5 pm.max_spare_servers = 20 pm.max_requests = 500 - Asegúrate de que
pm.max_childrensea estrictamente menor que el valor demax_connectionsde MySQL. - Guarda los cambios y reinicia PHP-FPM:
sudo systemctl restart php8.2-fpm
Por qué funciona: Al limitar pm.max_children, estableces un techo real al número de peticiones HTTP que PHP procesará simultáneamente. Esto previene que una ráfaga de tráfico cree más procesos PHP de los que MySQL puede gestionar.
Solución 4: Revisar la configuración de env.php de Magento 2 y desactivar conexiones persistentes
Magento 2 gestiona su conexión a la base de datos a través de PDO. Si en la configuración global se activan las conexiones persistentes sin una gestión adecuada del pool, las conexiones se acumulan rápidamente sin liberarse. Para errores generales de socket o puerto en MySQL, puedes revisar la guía sobre cómo solucionar el error SQLSTATE[HY000] [2002] en PHP y MySQL.
- Accede al directorio raíz de tu instalación de Magento 2.
- Abre el archivo de configuración del entorno ubicado en
app/etc/env.php:nano app/etc/env.php - Localiza la sección
db->connection->default. - Asegúrate de que no exista la opción
persistent => trueo cámbiala afalsedentro de las opciones del driver:'db' => [ 'connection' => [ 'indexer' => [ 'config' => [ 'model' => 'mysql4', 'engine' => 'innodb', 'initStatements' => 'SET NAMES utf8;', 'active' => '1' ], 'host' => 'localhost', 'username' => 'usuario_db', 'password' => 'password_db', 'dbname' => 'nombre_db', 'active' => '1' ], 'default' => [ 'config' => [ 'model' => 'mysql4', 'engine' => 'innodb', 'initStatements' => 'SET NAMES utf8;', 'active' => '1', 'driver_options' => [ \PDO::ATTR_PERSISTENT => false ] ], 'host' => 'localhost', 'username' => 'usuario_db', 'password' => 'password_db', 'dbname' => 'nombre_db', 'active' => '1' ] ] ] - Limpia la caché de Magento 2 para aplicar la configuración:
bin/magento cache:flush
Por qué funciona: Las conexiones no persistentes obligan a PHP a cerrar formalmente la toma de datos mediante el destructor de PDO al finalizar el ciclo de vida del script HTTP, devolviendo el socket al sistema.
Cómo comprobar que se ha solucionado
Para verificar que el sistema procesa las conexiones correctamente y no volverá a colapsar, ejecuta los siguientes comandos de supervisión:
- Accede a MySQL y monitoriza el uso de conexiones en tiempo real:
SHOW STATUS LIKE 'Threads_connected'; - Comprueba de nuevo el número máximo alcanzado desde el último reinicio:
SHOW STATUS LIKE 'Max_used_connections'; - Navega por la tienda online en varias pestañas o simula tráfico de prueba mediante una herramienta como Apache Bench o siege:
ab -n 100 -c 10 https://tudominio.com/ - Verifica que el parámetro
Threads_connectedsube y baja dinámicamente sin bloquearse al alcanzar el límite configurado enmax_connections.
Si nada de lo anterior funciona
Si el error 1040 Too many connections persiste tras aplicar los ajustes anteriores, revisa las siguientes vías de diagnóstico:
- Analizar el proceso lento (Slow Query Log): Activa el registro de consultas lentas en MySQL para identificar si hay tablas bloqueadas en las reindexaciones. Puedes profundizar sobre esto en la guía para diagnosticar y solucionar errores de reindexación en Magento 2.
- Revisar consultas activas con processlist: Ejecuta
SHOW FULL PROCESSLIST;en MySQL durante una caída para identificar qué script exacto está bloqueando la base de datos. - Escalar hardware (RAM y CPU): Cada conexión en MySQL consume memoria (mediante buffers como
read_buffer_size,sort_buffer_size). Si aumentasmax_connectionssin suficiente memoria RAM, el kernel de Linux activará el OOM Killer y detendrá el procesomysqld. Consulta la documentación oficial de MySQL sobre Too many connections para calcular el uso de memoria por hilo.
Preguntas frecuentes
¿Cuál es el valor recomendado de max_connections para Magento 2?
No existe un valor único. Para una tienda pequeña o mediana se recomienda un valor inicial entre 300 y 500. En sitios con alto tráfico se sitúa entre 800 y 1500, siempre condicionado a la memoria RAM disponible en el servidor.
¿Puedo cambiar max_connections sin reiniciar MySQL?
Sí, mediante el comando SET GLOBAL max_connections = valor; dentro de la consola de MySQL. Sin embargo, debes guardarlo en el archivo my.cnf para que el cambio no se pierda al reiniciar el servidor.
¿Afecta el uso de Redis o Varnish a este error?
Sí, de forma muy positiva. Utilizar Varnish para la caché de página completa (FDP) y Redis para la caché de sesión y backend evita que las peticiones de usuarios anónimos lleguen a PHP y MySQL, reduciendo drásticamente el número de conexiones necesarias.
¿Por qué aparece el error si tengo pocas visitas en mi tienda?
Suele ocurrir debido a tareas programadas (Cron) bloqueadas, bots o rastreadores web agresivos, o por scripts personalizados que abren transacciones sin finalizarlas correctamente, dejando hilos abiertos en estado inactivo.