Skip to content
Hosting Operations10 min read

MySQL Server Has Gone Away Not Working? 7 Fixes to Try

MySQL server has gone away not working? Compare 7 fixes—adjust timeouts, increase packet size, and tweak retries—to stop connection drops permanently.

Written by Abdul AbrorTechnical Hosting Support Engineer
Abstract visual of a severed database cable against a server rack, with a red 'gone away' warning glowing faintly in the background.
On this page

TL;DR — Key takeaways

  • Most 'gone away' errors stem from too-short timeouts or oversized queries; adjusting wait_timeout and max_allowed_packet resolves 90% of cases.
  • Server-side solutions outperform client-side retries for production stability—increase timeouts first, then add automatic reconnection logic.
  • If the error appears during long-running inserts, split batches and use persistent connections; for intermittent drops on shared hosting, switch to a provider that allows config tweaks.
  • Always back up my.cnf before changing server variables and test under load to avoid memory pressure from large max_allowed_packet values.
  • When the error only occurs with a specific CMS (like WordPress), check for plugin leaks or cron jobs holding stale connections; a code‑level fix may be quicker than server tuning.

You run a query, wait a few seconds, and your app spits out: MySQL server has gone away. The connection that was fine a moment ago is suddenly dead. I’ve seen this trip up everyone from first-time WordPress admins to seasoned infrastructure engineers.

The error isn’t one single problem—it’s a symptom with at least half a dozen distinct root causes. In this comparison, I’ll walk through those causes and three categories of fixes: server‑side configuration, client‑side retry logic, and environment‑specific workarounds. You’ll see the trade‑offs, get exact commands, and learn which path to pick based on your stack.

What “MySQL Server Has Gone Away” Actually Means

The message is literal. The MySQL client library attempted to send data over a TCP socket or Unix domain socket and received no response. The server vanished from the client’s perspective—either the connection was closed or the process died.

Under the hood, you’ll see error code 2006 in MySQL and MariaDB. It can surface during query execution, during a mysql_ping(), or even when calling mysqli::real_connect() if the previous persistent connection was dropped silently. The trigger could be anything from a 5‑minute idle timeout to a crashed daemon.

In support tickets I handle, this error often gets mixed up with error 2013 (“Lost connection to MySQL server during query”). They’re cousins—2013 typically means the connection broke mid‑query, while 2006 means the connection was gone before the query could even start. The fixes overlap, but timing matters.

Root Causes: Timeouts, Packets, and Server Crashes

Before picking a solution, you need to know why the server is going away. Here are the most common triggers, ranked from what I see daily to the edge cases that take a while to diagnose.

  • wait_timeout / interactive_timeout too low – MySQL drops idle connections after wait_timeout seconds (default 28800, but many shared hosts set it to 60‑120). Interactive clients have a separate interactive_timeout.
  • max_allowed_packet too small – If a query or result exceeds this limit (default 4‑16 MB), the server closes the connection immediately. Importing a large .sql file or sending a bulky BLOB is a classic trigger.
  • Server crash or restart – A mysqld crash looks exactly like ‘gone away’ because the socket disappears. Check dmesg or your error log for OOM‑killer messages.
  • Network interruption – Firewalls, NAT timeouts, or flaky VPC peering can drop idle TCP connections. Stateful firewalls often kill sessions after 5‑10 minutes.
  • Aborted connections from exceeding max_connections – When the connection limit is hit, new attempts fail with 1040, but existing connections may also be culled if there was a previous improper disconnect.
  • Client with an incorrect hostname resolution or skip‑name‑resolve mismatch – Rare, but if the server resolves the client hostname differently on each handshake, it can cause immediate 2006 errors.

Solution Set A: Server‑Side Configuration Tweaks

This is the first path I recommend because it fixes the problem at the source. Adjust the MySQL server’s own variables so it stops dropping connections that are actually healthy. The trade‑off? Higher memory use and the risk of letting zombie connections linger.

Start by checking your current values. Connect to MySQL and run: SHOW VARIABLES LIKE 'wait_timeout'; and SHOW VARIABLES LIKE 'max_allowed_packet';. Also check the global and session differences—some applications set a session variable that overrides the global one.

For a busy web app, I set the timeout to at least 1800 (30 minutes) or match the PHP max_execution_time plus some headroom. For max_allowed_packet, 64 MB is the sweet spot in 2026. Going higher than 256 MB risks memory exhaustion if multiple threads allocate large buffers simultaneously.

To apply permanently, edit your my.cnf (usually /etc/my.cnf or /etc/mysql/my.cnf) under the [mysqld] section:

wait_timeout = 1800

interactive_timeout = 1800

max_allowed_packet = 64M

Then restart MySQL: systemctl restart mysql (or mysqld). Test by running a query that previously failed. If you see the error return immediately after restart, the client may be setting a lower session timeout—check your framework’s connection pool config.

Solution Set B: Client‑Side Retry Logic and Connection Handling

Sometimes you can’t touch the server—shared hosting, managed databases, or a policy that forbids config changes. In those cases, you fix it from the application. The strategy: catch the 2006 error, reconnect, and retry.

Most modern database libraries already have an auto‑reconnect flag. PHP’s mysqli has $mysqli->options(MYSQLI_OPT_RECONNECT, true); but I’ll be blunt—it’s deprecated in PHP 8.2 and buggy under load. It reconnects silently, leaving prepared statements and transactions in an inconsistent state. Don’t rely on it.

A safer pattern is explicit reconnect‑on‑failure. Wrap your query function in a loop that catches the ‘gone away’ error, reconnects, and retries the query up to three times. Example in Python with SQLAlchemy: use pool_pre_ping=True to verify the connection before use. In PHP with PDO, set PDO::ATTR_TIMEOUT and implement a retry wrapper.

A transitional question: So what if the port is open but SSH still refuses? That’s a different beast, but the principle is the same—the lower the layer you fix it at, the more reliable the solution.

The downside? Retry logic adds complexity and can mask underlying problems. It also doesn’t help during long‑running queries that exceed the timeout while executing—by the time the error fires, rows may have been partially written. That’s why I combine client retries with query chunking: if you’re inserting 2 million rows, do it in batches of 10,000 so no single query runs longer than the timeout.

Head‑to‑Head: When to Tweak the Server vs. Fix the Client

Now for the comparison you’re after. The table below isn’t absolute—your mileage varies—but it captures what I’ve seen across hundreds of support tickets.

  • Fixes the root cause – Server‑side wins. Changing wait_timeout and max_allowed_packet prevents the error for every client. Client‑side merely recovers from it.
  • Immediate relief – Client‑side retry can be deployed in minutes without restarting services. Server changes need a MySQL restart or at least a rolling reload.
  • Risk of side effects – Server increases memory use; client retries can hide real crashes and cause duplicate operations if you don’t check for prior completion.
  • Shared hosting friendly – Client wins. You rarely have access to my.cnf on shared plans, but you can wrap a few lines of code in your CMS.
  • Long‑term stability – Server wins again. A properly configured server won’t surprise you at 3 a.m. when a new import hits the old packet limit.
  • My rule of thumb: If you control the server, start there—bump timeouts and packet size. Use client retries as a safety net, not a primary fix.

Quick Fixes for Shared Hosting and CMS‑Specific Issues

Shared hosting is the wild west. Providers often set wait_timeout to 60 seconds to reclaim resources. If you’re on cPanel, you might find a “MySQL® Variables” editor in the dashboard that lets you increase max_allowed_packet per‑session, but global changes are locked.

For WordPress: this error frequently appears during core or plugin updates, or when a plugin runs a cron job that holds an idle connection. First, add define('WP_MEMORY_LIMIT', '256M'); to wp-config.php—not directly a MySQL fix, but it helps if the error is a memory exhaustion cascade. Then install the WP Crontrol plugin, look for long‑running cron events, and stagger them.

For other CMSes, check the adapter’s persistent connection setting. Persistent connections seem efficient—they avoid reconnection overhead—but they’re notorious for ‘gone away’ errors because the connection can be silently dropped by the server without the client knowing. Disable persistent connections unless you have a connection pool that validates before use.

One more transitional note: So what if you’ve tried all that and the error still haunts you? The likely culprit is a network device timing out the TCP session. In that case, you need a keepalive.

Prevention and Monitoring (So It Stays Fixed)

Fixing the immediate error is step one. Step two: make sure it doesn’t come back next week. Turn on the general query log temporarily to spot abandoned connections—SET GLOBAL general_log = 'ON'; then tail /var/lib/mysql/hostname.log and look for connections that open but never close.

Set up alerting on two metrics: aborted_clients and aborted_connects. You can pull them with SHOW GLOBAL STATUS LIKE 'Aborted_clients';. If this number spikes, something is systematically killing connections. In your monitoring tool (Nagios, Prometheus + mysqld_exporter), graph these over time and alert on a doubling within 5 minutes.

Finally, schedule a regular connectivity check from a remote script. A simple bash one‑liner: mysqladmin -u user -p'pass' -h host ping || echo 'Connection lost'. Run it every minute and log failures. You’ll catch flaky network issues before your users do.

If you’re on a VPS or dedicated server, also watch for OOM kills: grep -i 'out of memory' /var/log/messages or journalctl -k | grep -i oom. MySQL is often the first victim when memory runs short, and the only real fix there is more RAM or a tuned innodb_buffer_pool_size.

Quick troubleshooting checklist

  • Back up your current my.cnf before making any changes: cp /etc/my.cnf /etc/my.cnf.bak.$(date +%F)
  • Connect to MySQL and note the current wait_timeout and max_allowed_packet: SHOW VARIABLES LIKE '%timeout%'; SHOW VARIABLES LIKE 'max_allowed_packet';
  • Double max_allowed_packet to 64M and increase wait_timeout to at least 600 seconds in the [mysqld] section of my.cnf
  • Restart MySQL and confirm the new values took effect with SHOW VARIABLES again
  • Reproduce the failing query—if the error persists, check if the client library sets a lower session timeout (e.g., PHP’s default_socket_timeout)
  • For applications that can’t change server config, add a three‑retry loop around database calls, with a fresh connection each time
  • Disable persistent connections in your CMS or framework, and enable client‑side TCP keepalive if supported (MySQL 8.0.13+ supports tcp_keepalive_time)
  • Set up monitoring on Aborted_clients metric and log OOM events to catch server-level crashes early

FAQ

Why does MySQL say ‘server has gone away’ during a large import?

The import likely contains a single INSERT or LOAD DATA statement whose size exceeds the server’s max_allowed_packet limit. When MySQL encounters a packet larger than this threshold (default often 16 MB), it immediately closes the connection. Increase max_allowed_packet to at least 64 MB in my.cnf, restart, and retry the import. If you can’t change the server setting, split the dump file into smaller chunks using tools like mysqldumpslow or sed.

Can I set max_allowed_packet to 1 GB?

Technically, yes—the maximum value is 1 GB. But it’s dangerous unless you have abundant RAM. MySQL allocates a buffer of this size per connection that requests it, so with 100 concurrent connections that’s 100 GB of memory just for packet buffers. Realistically, 64–256 MB covers 99% of use cases without risking OOM kills. Only push higher if you have a controlled batch job with a single dedicated connection.

Does PHP’s mysqli.reconnect fix it reliably?

No. The MYSQLI_OPT_RECONNECT flag is deprecated as of PHP 8.2 and will be removed in a future version. Even when it worked, it reconnected silently without restoring prepared statements, transaction state, or session variables—leading to subtle bugs. Instead, implement an explicit retry mechanism that catches the 2006 error, re‑connects, and re‑executes the query, or use a library that supports connection validation (like PDO with a custom reconnect wrapper).