Skip to content
Hosting Operations9 min read

MySQL Server Has Gone Away Fix: 7 Solutions (2026)

Fix MySQL server has gone away errors with seven proven methods. Compare timeout tweaks, packet limits, and connection pooling to stop disconnects.

Written by Abdul AbrorTechnical Hosting Support Engineer
graphical user interface, text, application
On this page

TL;DR — Key takeaways

  • The error appears when MySQL closes an idle connection, receives a packet larger than max_allowed_packet, or times out during a long query
  • Increase wait_timeout and interactive_timeout to 600+ seconds for applications that hold connections between requests
  • Raise max_allowed_packet to 64M or higher when importing large datasets or handling BLOB columns
  • Connection pooling with automatic reconnect prevents most timeout errors in production applications
  • Check server logs and SHOW VARIABLES output before changing configuration to confirm the actual cause

You run a query, walk away for coffee, come back to "MySQL server has gone away." Or you're importing a database dump and it dies halfway through. Both trace back to MySQL closing connections it thinks are dead or rejecting packets it considers too large.

In support tickets I handled, the usual culprit was one of three things: an idle connection timing out, a packet exceeding the server limit, or a query taking longer than MySQL would wait. The fix depends on which one you're hitting. This guide compares all seven methods, shows you how to identify the root cause, and walks through permanent configuration changes that stop the error from coming back.

What MySQL Server Has Gone Away Actually Means

MySQL error 2006 (CR_SERVER_GONE_ERROR) tells you the server closed the connection before your client finished using it. Error 2013 (CR_SERVER_LOST) means the connection dropped during a query. Both produce the same "server has gone away" message in most clients.

The server closes connections for specific reasons. An idle connection that exceeds wait_timeout gets killed. A packet larger than max_allowed_packet gets rejected and the connection closes. A query that takes longer than net_read_timeout or net_write_timeout to send or receive data will time out. A server crash or restart obviously drops all connections.

Check your MySQL error log first. Look for out-of-memory kills, segfaults, or restart messages. If the log is clean, the problem is almost always timeout or packet size configuration. You can rule out a packet issue quickly: if the error happens during SELECT queries or when the connection sits idle, it's not packet size.

Method Comparison: Which Fix Matches Your Cause

Different causes need different fixes. Here's how they compare:

  • **Increase wait_timeout and interactive_timeout**: Fixes idle connection timeouts. Best for web applications that reuse database connections across requests. Set both to 600 seconds (10 minutes) or higher. Takes effect after MySQL restart or with SET GLOBAL for new connections only. No downside except slightly more memory per lingering connection.
  • **Raise max_allowed_packet**: Fixes large query or import failures. Required when inserting BLOB data, restoring mysqldump files, or sending queries over 64MB. Set to 128M or 256M depending on your largest table row. Restart required or use SET GLOBAL. Uses more memory per connection thread.
  • **Adjust net_read_timeout and net_write_timeout**: Fixes slow network transfers or long-running single queries. Default is 30 seconds for each. Increase to 300+ for batch jobs over slow connections. Rarely the actual cause unless you see timeout exactly at 30 seconds during data transfer.
  • **Enable connection pooling with reconnect**: Application-level fix that works for any cause. Connection pool checks if a connection is alive before handing it out and reconnects automatically. Requires code changes but prevents most timeout errors without touching MySQL configuration.
  • **Use persistent connections carefully**: PHP's mysql_pconnect and similar features reuse connections across requests, which avoids reconnect overhead but can exhaust connection limits. Only useful if you've already fixed timeout settings. Not a fix on its own.
  • **Reduce connect_timeout**: Opposite problem—client gives up before server accepts connection. If your error happens immediately on connection attempt, not during a query, lower connect_timeout on the client side. Rare cause.
  • **Switch to Unix socket instead of TCP**: Eliminates network timeout variables entirely for local connections. Change host from 127.0.0.1 to localhost in your connection string to use /var/run/mysqld/mysqld.sock. Faster and no TCP overhead. Only works when application and MySQL run on the same machine.

Diagnosing the Exact Cause in Your Environment

Run these commands from a MySQL client to see current settings:

``` SHOW VARIABLES LIKE '%timeout%'; SHOW VARIABLES LIKE 'max_allowed_packet'; SHOW STATUS LIKE 'Aborted_clients'; SHOW STATUS LIKE 'Aborted_connects'; ```

High Aborted_clients means connections are closing unexpectedly—usually timeout related. High Aborted_connects means connection attempts fail—check connect_timeout or firewall rules. If max_allowed_packet shows 16M or 64M and you're importing large dumps, that's your issue.

Enable the general query log temporarily to see exactly which query triggers the error. Add these lines to my.cnf under [mysqld]:

``` general_log = 1 general_log_file = /var/log/mysql/query.log ```

Restart MySQL, reproduce the error, then check the log. The last query before the error is your culprit. Turn general_log back to 0 after testing—it kills performance in production.

Step-by-Step Configuration Changes

For timeout fixes, edit /etc/mysql/my.cnf (Debian/Ubuntu) or /etc/my.cnf (RHEL/CentOS). Add these lines under the [mysqld] section:

``` [mysqld] wait_timeout = 600 interactive_timeout = 600 max_allowed_packet = 128M net_read_timeout = 300 net_write_timeout = 300 ```

Those values work for most hosting environments. Adjust max_allowed_packet higher if you have tables with very large TEXT or BLOB columns. Restart MySQL with `sudo systemctl restart mysql` or `sudo service mysql restart`.

Verify the changes took effect: reconnect to MySQL and run `SHOW VARIABLES LIKE 'wait_timeout';`. You should see 600. If you see 28800 still, you edited the wrong file or put the settings under [client] instead of [mysqld].

For immediate testing without restart, run these as root MySQL user:

```sql SET GLOBAL wait_timeout = 600; SET GLOBAL interactive_timeout = 600; SET GLOBAL max_allowed_packet = 134217728; ```

These apply to new connections only. Existing connections keep their old settings. That's fine for testing but you still need the my.cnf changes to survive a reboot.

Application-Level Connection Handling

Configuration fixes help but application code should handle disconnects gracefully. A production app shouldn't crash just because a connection timed out.

Most database libraries offer connection pooling. In Python with SQLAlchemy, set pool_pre_ping=True to test connections before use:

```python engine = create_engine( 'mysql://user:pass@localhost/db', pool_pre_ping=True, pool_recycle=3600 ) ```

pool_recycle closes and replaces connections after one hour, which is shorter than any reasonable wait_timeout. pool_pre_ping sends a lightweight query before handing out a connection from the pool. If the connection is dead, SQLAlchemy reconnects transparently.

In PHP with PDO, enable exception mode and catch connection errors:

```php $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_PERSISTENT => false, PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4' ]; try { $pdo = new PDO($dsn, $user, $pass, $options); } catch (PDOException $e) { // Log and retry once sleep(1); $pdo = new PDO($dsn, $user, $pass, $options); } ```

That catches the initial connection failure and retries. For long-running scripts, wrap queries in try-catch and reconnect on error 2006. Don't use PDO::ATTR_PERSISTENT unless you've confirmed it won't exhaust max_connections under load.

Monitoring and Preventing Future Errors

After applying fixes, watch connection metrics for a few days. Run this query every hour:

```sql SHOW STATUS WHERE Variable_name IN ( 'Threads_connected', 'Max_used_connections', 'Aborted_clients', 'Aborted_connects' ); ```

Threads_connected should stay well below max_connections (default 151). If it climbs near the limit, you have a connection leak—connections aren't closing properly. Check application code for unclosed database handles.

Aborted_clients should stop increasing after your timeout fixes. If it keeps climbing, clients are still disconnecting unexpectedly. Check for application crashes, network issues, or queries that exceed even your new timeout values.

Set up monitoring alerts when Threads_connected exceeds 80% of max_connections. That gives you time to investigate before the server refuses new connections entirely. Most hosting control panels include MySQL monitoring. If not, Prometheus with mysqld_exporter works well.

For import jobs that run regularly, script them with error handling. A simple bash wrapper can retry on error 2006:

```bash #!/bin/bash for i in {1..3}; do mysql -u user -p database < dump.sql && break echo "Retry $i after MySQL error" sleep 5 done ```

That retries up to three times with a five-second pause between attempts. Handles transient network issues and server restarts. Use it in cron jobs or CI/CD pipelines.

When to Choose Each Solution

If your error happens when a script or connection sits idle, increase wait_timeout and interactive_timeout. That's the most common cause. Set both to 600 or higher.

If it happens during mysqldump restore or when inserting large rows, raise max_allowed_packet to 128M or 256M. Check your largest table with `SELECT MAX(LENGTH(column_name)) FROM table;` to size it appropriately.

If the error is intermittent and you can't pin it down, implement connection pooling with health checks in your application. That fixes most causes without requiring you to identify the exact trigger.

If you're running long batch queries over a slow network, increase net_read_timeout and net_write_timeout to 300 seconds. That's only necessary if you see timeout exactly at 30 seconds during query execution.

For local applications where MySQL and the app share a host, switch from TCP to Unix socket. Change your connection host from 127.0.0.1 to localhost. Faster and immune to TCP timeout issues.

Don't change max_connections unless Threads_connected approaches the limit. More connections use more RAM. Fix leaks and idle timeouts first.

Quick troubleshooting checklist

  • Check MySQL error log for OOM kills or crash patterns
  • Run SHOW VARIABLES LIKE '%timeout%' and note current values
  • Run SHOW VARIABLES LIKE 'max_allowed_packet' to see packet limit
  • Test configuration changes in a non-production environment first
  • Monitor connection count with SHOW STATUS LIKE 'Threads_connected' after changes
  • Enable application-level connection retry logic
  • Set up query logging temporarily if errors happen during specific operations

FAQ

What causes MySQL server has gone away error?

MySQL closes the connection when it sits idle longer than wait_timeout (default 28800 seconds), when a query packet exceeds max_allowed_packet (default 64MB in MySQL 8.0), when a query runs longer than net_read_timeout or net_write_timeout, or when the server restarts or crashes. The client sees error 2006 or 2013 when it tries to use a closed connection.

How do I fix MySQL server has gone away permanently?

Add wait_timeout=600, interactive_timeout=600, and max_allowed_packet=128M to your my.cnf or my.ini file under [mysqld], then restart MySQL. For application code, implement connection pooling with health checks and automatic reconnect on stale connections. This combination handles both timeout and packet size causes.

Can I fix MySQL gone away error without restarting MySQL?

Yes, run SET GLOBAL wait_timeout=600; and SET GLOBAL max_allowed_packet=134217728; from a MySQL client. These take effect immediately for new connections. Existing connections keep their original settings until they reconnect. Configuration file changes are still needed to survive a server restart.