Overview
A MySQL connection timeout error means your application tried to open or use a database connection, and MySQL either dropped it before the query ran or refused it entirely. You’ll usually see something like MySQL server has gone away, Lost connection to MySQL server during query, or a generic Can't connect to MySQL server in your error logs.
This happens in a few distinct scenarios: an idle connection sat open too long and MySQL closed it on its end, the server hit its connection limit, a query ran too long and was killed, or there’s a networking issue between your app and the database. Each cause has a different fix, and applying the wrong one wastes time.
This article covers all of them. Whether you’re on shared hosting, a VPS SSD Hosting plan, or a dedicated server, the underlying MySQL/MariaDB behaviour is the same — only where you change the config differs.
Prerequisites
- SSH access to your server, or access to cPanel’s phpMyAdmin and MySQL configuration tools
- MySQL 5.7+ or MariaDB 10.3+ (commands shown work on both unless noted)
- For VPS/dedicated:
sudoor root access to edit/etc/my.cnfor/etc/mysql/mysql.conf.d/mysqld.cnf - Access to your application’s error logs — you’ll need the exact error message to diagnose correctly
- If you’re on shared hosting, you may not be able to change global MySQL variables; contact support for timeout adjustments
Step-by-Step Instructions
Step 1: Identify the Actual Error
Before changing anything, confirm which timeout error you’re dealing with. The fix for MySQL server has gone away is different from Too many connections. Check your app’s error log first.
On a cPanel server, WordPress errors are typically in /home/username/public_html/wp-content/debug.log if WP_DEBUG_LOG is enabled. For raw MySQL errors on a VPS:
sudo tail -n 100 /var/log/mysql/error.log
Note the exact message. Then continue to the relevant step below.
Step 2: Check Current Timeout Values in MySQL
Log into MySQL and check what your server is currently configured to do with idle or long-running connections:
SHOW VARIABLES LIKE '%timeout%';
SHOW VARIABLES LIKE 'max_connections';
SHOW STATUS LIKE 'Threads_connected';
The two most important values are wait_timeout (how long MySQL waits before closing an idle non-interactive connection) and interactive_timeout (same, for interactive sessions like a terminal). Default is 28800 seconds (8 hours) on most installs, but many hosting environments set this much lower — sometimes as short as 60 seconds.
📝 Note: Threads_connected shows active connections right now. If it’s close to max_connections, you’re hitting connection exhaustion, not just a timeout.
Step 3: Fix Idle Connection Timeouts (wait_timeout)
If you’re seeing MySQL server has gone away or Lost connection to MySQL server, the most common cause is that your app held a connection open longer than wait_timeout allows. MySQL silently closed it, but the app tried to reuse it.
On a VPS or dedicated server, edit your MySQL config file. The file location varies by distro:
- Ubuntu/Debian:
/etc/mysql/mysql.conf.d/mysqld.cnf - CentOS/AlmaLinux/Rocky:
/etc/my.cnfor/etc/my.cnf.d/server.cnf
Add or update these values under [mysqld]:
[mysqld]
wait_timeout = 300
interactive_timeout = 300
300 seconds (5 minutes) is a reasonable middle ground for most web apps. Don’t set it too high on shared or resource-limited servers — idle connections still consume memory.
After editing, restart MySQL:
# systemd (most modern distros)
sudo systemctl restart mysql
# or MariaDB:
sudo systemctl restart mariadb
⚠ Warning: Restarting MySQL briefly drops all active connections. Do this during a low-traffic window.
Step 4: Fix Connection Pool Exhaustion (max_connections)
If you’re seeing Too many connections, MySQL has hit its max_connections limit. Every new connection attempt is refused until an existing one closes.
First, check if this is actually the issue — don’t raise the limit blindly:
SHOW STATUS LIKE 'Max_used_connections';
SHOW STATUS LIKE 'Connection_errors_max_connections';
If Connection_errors_max_connections is above 0, you’ve hit the limit at least once since the last restart.
To increase it, add to [mysqld] in your config file:
max_connections = 200
📝 Note: The default is 151. Each connection uses roughly 1–2 MB of RAM depending on query complexity. On a 2 GB VPS, setting this to 500 can cause MySQL to OOM-kill itself under load. Match the value to your available RAM, not just your desired connection count.
The non-obvious fix here is often not raising the limit, but fixing the application side: enable connection pooling (PgBouncer for Postgres, or MySQLnd connection pool for PHP), or ensure your app closes connections properly after each request. Raising max_connections on a leaky app just delays the crash.
Step 5: Fix Query Execution Timeouts
If a specific query is being killed mid-run, you’re hitting net_read_timeout or net_write_timeout, or in some cases innodb_lock_wait_timeout on locked rows. Check your error log for Lock wait timeout exceeded.
SHOW VARIABLES LIKE 'innodb_lock_wait_timeout';
SHOW VARIABLES LIKE 'net_read_timeout';
SHOW VARIABLES LIKE 'net_write_timeout';
For lock wait issues, the real fix is optimising the query or transaction causing the lock, not just raising the timeout. But as a short-term measure:
[mysqld]
innodb_lock_wait_timeout = 60
net_read_timeout = 60
net_write_timeout = 60
⚠ Warning: If you’re repeatedly hitting lock timeouts, that’s a sign of a slow query or missing index holding a lock too long. Check SHOW ENGINE INNODB STATUSG to see what’s blocking what.
Step 6: Verify the Changes Took Effect
After restarting MySQL, confirm the new values are live without assuming the restart worked cleanly:
SHOW VARIABLES LIKE 'wait_timeout';
SHOW VARIABLES LIKE 'max_connections';
If they haven’t changed, your config file edit may be in the wrong section or wrong file. Run mysql --verbose --help | grep my.cnf to see which config files MySQL is actually reading and in what order.
Common Issues & Troubleshooting
“MySQL server has gone away” on every page load
This usually means wait_timeout on the server is very low (under 30 seconds), and your application framework is reusing a cached connection that MySQL already closed. The fix is either raising wait_timeout as shown in Step 3, or configuring your app to reconnect automatically. In PHP, adding PDO::ATTR_PERSISTENT => false or enabling mysqli’s auto-reconnect can help, but the real fix is connection pooling or shorter-lived connections.
Timeout errors only under high traffic
This is almost always max_connections exhaustion combined with slow queries holding connections open longer than normal. Run SHOW PROCESSLIST; during the traffic spike to see what’s piling up. If you see dozens of queries in a Waiting for table metadata lock state, one slow query is holding a table lock and a queue is forming behind it. Kill the offending process with KILL [process_id]; as a short-term fix, then identify and optimise that query.
Config changes not persisting after MySQL restart
On AlmaLinux 8+ and Ubuntu 22.04+, MySQL and MariaDB sometimes read from multiple config directories and the order matters. Your edit might be in a file that’s being overridden by another. Run this to see the full config load order:
mysqld --verbose --help 2>/dev/null | grep -A1 'Default options'
Put your settings in the file listed last — it wins. On many cPanel servers, the correct file is /etc/my.cnf, and WHM’s MySQL Configuration Editor will overwrite other locations.
Timeout errors on a managed WordPress site
On Host & Tech managed WordPress hosting, database connection settings are managed at the server level. If you’re seeing timeout-related errors like Error establishing a database connection, check your wp-config.php credentials first — that error can be a timeout or simply wrong credentials. If credentials are correct, contact support to review the MySQL timeout configuration for your account, as you won’t have direct access to my.cnf.
“Lost connection to MySQL server during query” on large imports
This one is specifically caused by max_allowed_packet being too small, or net_read_timeout being too short for large data transfers — not a standard idle timeout. If you’re importing a large SQL file via phpMyAdmin or CLI and it cuts off, add this to [mysqld]:
max_allowed_packet = 256M
net_read_timeout = 120
For CLI imports, you can also set it per-session without touching the config file:
mysql --max_allowed_packet=256M -u username -p dbname < import.sql
FAQ
Frequently Asked Questions
What does MySQL wait_timeout actually do?
It’s the number of seconds MySQL will wait on an idle, non-interactive connection before closing it automatically. If your app opens a database connection and then doesn’t use it for longer than that value, MySQL drops it from its end. The next time your app tries to run a query on that connection, it gets a ‘MySQL server has gone away’ error. Setting it too low causes frequent drops; too high wastes server memory on idle connections.
Can I fix MySQL connection timeouts without SSH access?
It depends on the error. If you’re on a shared hosting plan, you can’t edit my.cnf directly. For wait_timeout and similar global variables, you’d need to contact your host. However, if the issue is on the application side — like a WordPress plugin holding connections open — you can fix that from within wp-config.php or your app settings without server access.
How do I check if max_connections is the problem?
Log into MySQL and run SHOW STATUS LIKE ‘Connection_errors_max_connections’; — if that number is greater than zero, you’ve hit the limit at least once since the last MySQL restart. Also check SHOW STATUS LIKE ‘Max_used_connections’; and compare it to SHOW VARIABLES LIKE ‘max_connections’; to see how close you’ve been cutting it.
Will raising max_connections fix my timeout errors?
Sometimes, but not always. If you’re hitting ‘Too many connections’, raising max_connections gives you breathing room. But if the real problem is slow queries holding connections open, you’re just delaying the same crash with a higher ceiling. Check SHOW PROCESSLIST; to see if connections are genuinely queuing up or if a handful of slow queries are blocking everything.
Does MySQL timeout configuration differ between MySQL 8 and MariaDB 10.x?
The core timeout variables (wait_timeout, interactive_timeout, max_connections) work the same on both. The main difference that catches people out is authentication: MySQL 8 defaults to caching_sha2_password, while MariaDB uses mysql_native_password. This can cause connection failures that look like timeout errors but are actually auth rejections. If you’ve recently migrated between the two, check your user plugin with SELECT user, plugin FROM mysql.user;