MySQL Too Many Connections
Fix the "Too many connections" error in MySQL and MariaDB, tune max_connections, find connection leaks, and implement connection pooling
The ERROR 1040 (HY000): Too many connections error means MySQL has hit its connection limit. Every new connection attempt is rejected until an existing one closes.
Immediate fix: increase the limit temporarily
Connect as root (if you can still get in, root always gets one reserved connection):
sudo mysql -u root -p-- Check current limit
SHOW VARIABLES LIKE 'max_connections';
-- Increase temporarily (takes effect immediately, resets on restart)
SET GLOBAL max_connections = 500;
-- Check how many connections are currently open
SHOW STATUS LIKE 'Threads_connected';
-- Check the all-time peak
SHOW STATUS LIKE 'Max_used_connections';Permanent fix: edit the config
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
# MariaDB:
sudo nano /etc/mysql/mariadb.conf.d/50-server.cnfAdd or update:
[mysqld]
max_connections = 500Restart:
sudo systemctl restart mysqlHow many connections do you need?
-- Check peak usage over server lifetime
SHOW STATUS LIKE 'Max_used_connections';Set max_connections to ~20% above your peak. Keep in mind each connection uses ~1-8 MB RAM depending on queries.
Diagnose: find who is using all connections
-- List all current connections
SHOW PROCESSLIST;
-- Group by user and host to find the culprits
SELECT user, host, COUNT(*) AS connections
FROM information_schema.processlist
GROUP BY user, host
ORDER BY connections DESC;
-- Show sleeping (idle) connections
SELECT user, host, command, time, state
FROM information_schema.processlist
WHERE command = 'Sleep'
ORDER BY time DESC;Kill idle connections
If many connections are in Sleep state for a long time, they're leaked by applications that don't close connections properly:
-- Kill a specific connection (get ID from SHOW PROCESSLIST)
KILL CONNECTION 1234;
-- Kill all sleeping connections (run this carefully)
SELECT CONCAT('KILL ', id, ';')
FROM information_schema.processlist
WHERE command = 'Sleep' AND time > 300;
-- Copy and paste the output to executeFix connection timeout settings
Reduce how long idle connections are kept open:
[mysqld]
wait_timeout = 60
interactive_timeout = 60wait_timeout: close connections idle for 60 seconds (non-interactive)interactive_timeout: close interactive sessions idle for 60 seconds
Apply without restart:
SET GLOBAL wait_timeout = 60;
SET GLOBAL interactive_timeout = 60;Find connection leaks in your application
Connection leaks happen when code opens DB connections but doesn't close them. Common causes:
PHP (PDO/mysqli):
// Bad, connection never closed
$pdo = new PDO($dsn, $user, $pass);
$pdo->query("SELECT ...");
// Script ends but connection lingers in persistent pool
// Good, explicitly close
$pdo = new PDO($dsn, $user, $pass);
$pdo->query("SELECT ...");
$pdo = null; // closes connectionNode.js:
// Bad, new connection per query
const conn = mysql.createConnection(config);
conn.query('SELECT ...', (err, rows) => {
// forgot to conn.end()
});
// Good, use a connection pool
const pool = mysql.createPool({ ...config, connectionLimit: 10 });
pool.query('SELECT ...', (err, rows) => { ... });Implement connection pooling
Instead of each app instance opening many connections, a pool reuses a fixed number:
MySQL/MariaDB: ProxySQL (connection pooler):
sudo apt install proxysql -yProxySQL sits between your app and MySQL, multiplexing thousands of app connections into a small pool of real MySQL connections.
PHP: PHP-FPM + persistent connections
In php.ini:
; Use persistent connections (reused across requests)
; Only if your app handles this correctly
mysql.allow_persistent = On
mysql.max_persistent = 10Simpler: limit connections per app
In your app's DB config, set a pool size that fits within max_connections:
# Example: 5 workers × 10 pool size = 50 connections max per app
DB_POOL_SIZE=10Monitor connections over time
-- Current connections
SHOW STATUS LIKE 'Threads_connected';
-- Peak connections since last restart
SHOW STATUS LIKE 'Max_used_connections';
-- Total connection attempts (including refused)
SHOW STATUS LIKE 'Connection_errors_max_connections';Set up a cron job to log connection counts:
echo "$(date): $(mysql -u root -p'pass' -e 'SHOW STATUS LIKE "Threads_connected"' -s -N | awk '{print $2}') connections" >> /var/log/mysql-connections.logQuick reference
| Symptom | Cause | Fix |
|---|---|---|
ERROR 1040 Too many connections | Hit max_connections | Increase max_connections |
Many Sleep connections | App not closing connections | Reduce wait_timeout |
| Spike at peak traffic | Pool too small | Use connection pooler (ProxySQL) |
| App reconnects constantly | Low wait_timeout | Balance timeout vs pool size |