Emergency server help: get in touch

MySQL ERROR 1040 Too Many Connections: Fixes for cPanel

Sites throw "Error establishing a database connection" and the MySQL error log says "Too many connections". Here is how to get the server back in two minutes, find what actually caused it, and set limits so it does not come back.

Published Updated 4 min read

The exact message is ERROR 1040 (08004): Too many connections in the mysql client, or SQLSTATE[HY000] [1040] Too many connections in PHP and WordPress logs. Both mean the server has reached max_connections; a per-user limit gives a different error (1203, max_user_connections).

Get the server responding first

If every site on the box is down, do not start tuning. Get in and clear the pile-up. MariaDB reserves one extra connection for a SUPER user, so as root you can usually still connect even when the limit is hit:

mysql -e "SHOW PROCESSLIST" | head -40
mysql -e "SHOW GLOBAL STATUS LIKE 'Threads_connected'; SHOW VARIABLES LIKE 'max_connections'"

If the process list is full of Sleep rows from one database user, that user’s application is opening connections and never closing them. Kill the sleepers older than a minute to free the server immediately:

mysql -Nse "SELECT CONCAT('KILL ',id,';') FROM information_schema.processlist WHERE command='Sleep' AND time>60" | mysql

If instead the list is full of long-running SELECTs in state Sending data or Copying to tmp table, one query is holding everything up. Note the query text, then kill only those IDs. Restarting MariaDB is the last resort — it works, but you lose the evidence.

Find the real cause

“Too many connections” is a symptom. Before raising any limit, spend five minutes on where the connections came from:

  • A slow query. Enable the slow log for an hour: SET GLOBAL slow_query_log=1; SET GLOBAL long_query_time=2; then read /var/lib/mysql/<host>-slow.log or run mysqldumpslow -s t -t 10 on it. A query that takes eight seconds on a busy WordPress site will hold dozens of connections open behind it.
  • A traffic spike or bot. tail -5000 /etc/apache2/logs/domlogs/<domain> | awk '{print $1}' | sort | uniq -c | sort -rn | head shows whether one IP is hammering a site. Block it in CSF and the connections drain on their own.
  • A leaking application. Persistent connections (mysqli.allow_persistent, PDO ATTR_PERSISTENT) with PHP-FPM can multiply: every FPM child keeps its own. Check with SHOW PROCESSLIST grouped by user.
  • Lock waits. SHOW ENGINE INNODB STATUS\G under TRANSACTIONS shows if queries are queued behind a lock, often from a plugin doing ALTER TABLE or a backup job with LOCK TABLES.

The mysql-health-snapshot script prints most of these numbers on one page.

Set the limit properly

cPanel ships max_connections=151, the MariaDB default. On a shared server with 50+ sites it is too low; on a single-site VPS with 2 GB of RAM it may be too high. Each connection can use up to sort_buffer_size + read_buffer_size + read_rnd_buffer_size + join_buffer_size + thread_stack (typically 1–4 MB), so 500 connections on a small box can run you out of memory and make things worse.

Edit /etc/my.cnf under [mysqld]:

max_connections        = 300
wait_timeout           = 120
interactive_timeout    = 120
thread_cache_size      = 32
open_files_limit       = 65535

wait_timeout is the important one: it closes idle connections after 120 seconds instead of the default 8 hours, which is what lets a leaking application fill the table in the first place. Restart with systemctl restart mariadb in a quiet minute, or apply live without restarting:

mysql -e "SET GLOBAL max_connections=300; SET GLOBAL wait_timeout=120;"

Live changes are lost on restart, so put them in my.cnf too.

Stop it from coming back

Give PHP-FPM a ceiling per site (pm.max_children) in WHM → MultiPHP Manager → PHP-FPM settings, so one busy site cannot open more MySQL connections than the server can serve. Turn on object caching (Redis or LiteSpeed Cache’s object cache) for WordPress sites; it cuts query count by 60–80% on typical pages. And keep the slow log on permanently with long_query_time=5 — it costs nothing and tells you which site to look at next time.

MySQL too many connections at a glance

MySQL Too Many Connections summary card: If every site on the box is down, do not start tuning.
In short: If every site on the box is down, do not start tuning.

Official documentation: MySQL reference manual, MariaDB documentation, cPanel & WHM documentation.

Related guides: Tuning InnoDB on MariaDB 11/12 for cPanel shared hosting: buffer pool, redo log and I/O · MariaDB won’t start after an upgrade: InnoDB recovery, mariadb-upgrade and sql_mode issues · Installing and switching PHP versions in EasyApache 4 (8.2 to 8.5).

Free website test

Is your website set up right?

Check SSL, security headers, redirects, robots.txt, sitemap, llms.txt and security.txt in one test. It takes about 30 seconds.