← Debugging Guides

阅读中文版本

MySQL ERROR 1040 Too many connections — Diagnose and Fix

Diagnose MySQL ERROR 1040 by measuring Threads_connected against max_connections, inspecting processlist sleepers, then fixing leaks, wait_timeout, and pool sizing.

intermediatedebuggingmysqlconnections

Symptoms

  • ERROR 1040 (HY000): Too many connections
  • New application requests fail while existing sessions continue to work
  • Threads_connected sits at or above max_connections
  • Processlist is full of Sleep sessions owned by the application user

Possible causes

  • The application pool opens more connections than the server is sized for
  • Connections leak because code paths never close them or a pool has no maximum
  • wait_timeout is high and abandoned sessions stay Sleep for hours
  • A traffic spike, cron job, or reporting tool created a second pool against the same database

Diagnosis steps

Compare current connections with the configured ceiling

mysql -uroot -p -e "SHOW STATUS LIKE 'Threads_connected'; SHOW STATUS LIKE 'Threads_running'; SHOW VARIABLES LIKE 'max_connections'; SHOW VARIABLES LIKE 'wait_timeout';"

Interpretation

Threads_connected near max_connections confirms exhaustion. Threads_running much lower means most sessions are idle, which points to pooling or leaks rather than CPU load.

Group sessions by user, host, and state

mysql -uroot -p -e "SELECT user, host, db, command, COUNT(*) AS sessions, MAX(time) AS max_idle FROM information_schema.processlist GROUP BY user, host, db, command ORDER BY sessions DESC;"

Interpretation

Many Sleep rows from one service indicate leaked or oversized pools. Long Query rows from a single host suggest a runaway report or lock wait.

Find the oldest idle sessions

mysql -uroot -p -e "SELECT id, user, host, db, command, time, state, LEFT(info, 60) AS query FROM information_schema.processlist WHERE command = 'Sleep' ORDER BY time DESC LIMIT 20;"

Interpretation

Idle times close to wait_timeout show sessions that will soon expire. Uniform idle times across hundreds of rows usually mean a pool that keeps opening new connections.

Use the administrative connection when the normal limit is reached

mysql --admin -uroot -p -e "SELECT id, user, host, command, time FROM information_schema.processlist ORDER BY time DESC LIMIT 20;"

Interpretation

The admin interface bypasses max_connections on MySQL 8.0.14 and later, so you can inspect the server without killing an application session.

Root cause

MySQL admits at most max_connections simultaneous client sessions, with one extra reserved for users holding the CONNECTION_ADMIN privilege. When every slot is occupied, new TCP handshakes complete but the server returns ERROR 1040 before authentication. Idle Sleep sessions still count against the limit, so a pool that never releases connections can exhaust the server without any slow query.

Fix

Right-size each application pool and cap it well below max_connections divided by the number of replicas. Close connections in finally blocks, set a sensible wait_timeout, and put a proxy such as ProxySQL in front when many clients share one server. Raise max_connections only after checking memory and thread overhead, since each session consumes per-thread buffers.

Risk note

Killing sessions with KILL CONNECTION rolls back their transaction and can interrupt batch work. Raising max_connections increases memory use and context switching; it does not repair a leak. The extra administrative slot does not help if the OS file descriptor limit is also exhausted.

Verify the fix

Watch Threads_connected over a full traffic cycle and confirm it stays below the configured pool total. Reconnect from an application replica during peak load and verify no ERROR 1040 appears, with Threads_running well under max_connections.

1040 is admission control, not authentication

ERROR 1040 (HY000): Too many connections is returned after the TCP connection is accepted but before the client is authenticated. MySQL has no free session slot, so credentials are never checked. One slot is reserved for accounts with CONNECTION_ADMIN, which is why a DBA can sometimes log in while the application cannot.

SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Threads_running';
SHOW VARIABLES LIKE 'max_connections';

If Threads_connected is at the ceiling and Threads_running is low, the sessions are idle rather than busy. That distinction decides whether you need pool tuning or query tuning.

Read the processlist in aggregate

SELECT user, host, db, command, COUNT(*) AS sessions, MAX(time) AS max_idle
FROM information_schema.processlist
GROUP BY user, host, db, command
ORDER BY sessions DESC;

Hundreds of Sleep rows from one host usually mean a pool with no maximum or a framework opening a connection per request. A few long Query rows mean a lock wait or a runaway report holding a slot.

Fix sizing and lifecycle

Set each pool’s maximum explicitly and multiply by replica count before comparing with max_connections. Add wait_timeout and interactive_timeout appropriate to your traffic, close connections in finally blocks, and deploy ProxySQL or MySQL Router when many clients share the server. Increase max_connections only after checking Threads_running and memory headroom, because every session allocates buffers.

When you must reclaim capacity immediately, prefer terminating idle sessions belonging to a known leaky client rather than restarting MySQL.

Verify under load

Run the load test again and sample Threads_connected every few seconds. It should plateau below the sum of pool limits, and a fresh application connection should succeed while traffic is at its peak. Check SHOW GLOBAL STATUS LIKE 'Aborted_connects'; before and after; a rising value means clients still hit the ceiling or fail authentication.