Common Issues

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.cnf

Add or update:

[mysqld]
max_connections = 500

Restart:

sudo systemctl restart mysql

How 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 execute

Fix connection timeout settings

Reduce how long idle connections are kept open:

[mysqld]
wait_timeout = 60
interactive_timeout = 60
  • wait_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 connection

Node.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 -y

ProxySQL 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 = 10

Simpler: 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=10

Monitor 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.log

Quick reference

SymptomCauseFix
ERROR 1040 Too many connectionsHit max_connectionsIncrease max_connections
Many Sleep connectionsApp not closing connectionsReduce wait_timeout
Spike at peak trafficPool too smallUse connection pooler (ProxySQL)
App reconnects constantlyLow wait_timeoutBalance timeout vs pool size

On this page