Common causes
- Slow queries or lock waits keep connections busy while new requests keep arriving
- Persistent connections (PDO::ATTR_PERSISTENT, mysqli p:) or connection pools that never release
- Too many PHP-FPM workers compared with max_connections (default 151)
- A traffic spike, bot crawl or cron job storm opening many connections at once
- A long wait_timeout leaving thousands of idle Sleep connections
- A per-user cap set by max_user_connections on shared hosting (ERROR 1203)
How to fix it
- See who holds the connections. Log in (MySQL keeps one extra slot for an admin with CONNECTION_ADMIN or SUPER) and run SHOW FULL PROCESSLIST; Group by user, host and Command to see whether they are Sleep or long Query states.
- Kill stuck or idle sessions. Use KILL <id>; for runaway queries or long Sleep sessions. This frees slots immediately while you fix the cause.
- Fix the slow queries. Enable the slow query log and add indexes or rewrite the queries that pile up. Shorter queries release connections faster than any setting change.
- Lower idle timeouts. Set wait_timeout and interactive_timeout to 300-600 seconds so abandoned connections close. Disable persistent connections in PHP unless you have measured a benefit.
- Match workers to max_connections. Keep pm.max_children across all PHP-FPM pools (plus cron and workers) below max_connections. If you have the RAM, raise max_connections to 300-500 in my.cnf and restart.
- Add caching or a proxy. A page cache or object cache cuts database hits per request. For very high traffic, ProxySQL or MaxScale can pool and limit connections.
my.cnf ([mysqld] section)
[mysqld]
max_connections = 300
wait_timeout = 600
interactive_timeout = 600
-- check usage at runtime:
-- SHOW GLOBAL STATUS LIKE 'Max_used_connections';
-- SHOW VARIABLES LIKE 'max_connections'; How to stop it happening again
- Watch Max_used_connections and alert when it approaches max_connections
- Keep the slow query log on and review it after each release
- Size PHP-FPM and worker pools against the database limit, not just CPU
- Rate-limit aggressive bots and stagger cron jobs that hit the database