SQLSTATE[HY000] [2002] Connection refused or MySQL server has gone away

MySQL Connection Pool Exhausted – Three Common Fixes

Your app can't open new MySQL connections because all are in use. Here's the real fix for each common cause — no fluff.

You're getting 'too many connections' or 'connection pool exhausted'. Your app can't talk to the database. What's actually happening here is that MySQL has a hard limit on how many connections it can handle at once. When all those slots are full, new connections get rejected.

I've seen this error in PHP apps with PDO, Node.js with mysql2, and Python with SQLAlchemy. The fix depends on which of the three common causes you're hitting. Let's start with the one that fixes 80% of cases.

Cause #1 – Connections not being closed after use

This is the most common. Your code opens a connection but never closes it explicitly. In PHP with PDO, if you don't set the connection object to null, the connection stays open until the script ends. But if your script is long-running (like a worker queue), that connection never dies.

Here's the real fix: for short scripts, wrap your PDO connection in a try-finally block and close it in the finally block. For long-running processes, use a connection pool library that manages the lifecycle for you.

Example fix for PHP PDO:

$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);

try {
    // your queries
} finally {
    $dbh = null; // this actually closes the connection
}

The reason this works: setting the PDO object to null triggers PHP's destructor, which sends a QUIT command to MySQL. Without it, the connection sits idle until MySQL's wait_timeout kicks in (default 8 hours).

For Node.js with mysql2, never leave a connection hanging. Always call connection.release() or pool.end() after your query.

Cause #2 – max_connections set too low for your workload

Your code is clean, connections close properly, but you still hit the limit. Check your MySQL config:

SHOW VARIABLES LIKE 'max_connections';

Default is 151 for MySQL 8.0. If your app has 100 web servers each holding 5 connections in a pool, that's 500 connections right there. You'll exhaust 151 fast.

The fix: increase max_connections in your my.cnf file. But don't go wild. Each connection uses RAM (about 256KB to 1MB depending on buffers). I've seen people set it to 1000 on a 2GB server and crash from memory exhaustion.

For production, use this formula:

max_connections = (available_ram * 0.8) / per_connection_ram

Where per_connection_ram you can estimate from SHOW GLOBAL STATUS LIKE 'Max_used_connections' and SHOW GLOBAL STATUS LIKE 'Threads_connected'.

Also consider using a connection pool in your app with a fixed size. For example, in a Java app with HikariCP, set maximumPoolSize to something like 20. That way your app doesn't open infinite connections.

Cause #3 – Abandoned connections from killed or timed-out queries

This one's trickier. Your code closes connections, your pool size is reasonable, but connections still pile up. Look at SHOW PROCESSLIST. See a bunch of connections in 'Sleep' state or 'Query' state from hours ago?

What's actually happening here is a query took too long (longer than wait_timeout or interactive_timeout), MySQL killed it, but the application didn't detect the death. The app thinks it has an open connection, but it's dead on the server side. Eventually all pool slots get filled with these zombie connections.

The fix: set wait_timeout and interactive_timeout to something reasonable for your app. 30 seconds to 5 minutes is typical for web apps. Also enable skip_name_resolve to avoid DNS delays that can cause timeouts.

Run this in MySQL:

SET GLOBAL wait_timeout = 300;
SET GLOBAL interactive_timeout = 300;

And add to my.cnf:

[mysqld]
wait_timeout = 300
interactive_timeout = 300
skip_name_resolve

For apps using PDO, also set PDO::ATTR_TIMEOUT to 2 seconds so your app doesn't hang waiting for a dead connection.

Quick reference table

CauseSymptomFix
Unclosed connectionsConnections stay in 'Sleep' stateClose connections explicitly in code; use try-finally
Low max_connectionsError says 'too many connections'Increase max_connections; add app-level connection pool
Abandoned dead connectionsZombie connections in process listReduce wait_timeout; enable skip_name_resolve; detect dead connections

Start with cause #1. That's where I've seen 9 out of 10 cases of connection pool exhaustion. If that doesn't fix it, check your max_connections and timeout settings. Don't just increase limits blindly — find the root cause first.

Related Errors in Database Errors
MySQL Slow Query Log Filling Disk – Real Fix 0X801F001B ERROR_FLT_ALREADY_ENLISTED (0x801F001B) Fix 0XC00D0FF0 Fix NS_E_WMP_SAVEAS_READONLY (0XC00D0FF0) in WMP 0X00001AA5 0X00001AA5: Transaction manager already consistent

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.