Skip to content
Hosting Operations9 min read

MySQL Server Has Gone Away Troubleshoot: 7 Fixes

Fix the MySQL server has gone away error by comparing timeout adjustments, packet size changes, and connection pooling. Choose the right solution for your

Written by Abdul AbrorTechnical Hosting Support Engineer
text
On this page

TL;DR — Key takeaways

  • The error happens when MySQL closes idle connections after wait_timeout expires (default 28800 seconds) or when queries exceed max_allowed_packet size.
  • For web apps with short requests, increase wait_timeout to 600-1800 seconds; for long-running batch jobs, use max_allowed_packet adjustments instead.
  • Connection pooling prevents most timeout issues by keeping connections active, but requires application-level changes.
  • Always test configuration changes on a staging server first and monitor memory usage when increasing packet or connection limits.

The MySQL server has gone away error shows up at the worst possible time. Your application was working fine, then suddenly every query fails with a cryptic message. In support tickets I handled, the usual culprit was a connection that sat idle too long or a query that sent more data than MySQL expected.

This guide compares the main fixes—timeout adjustments, packet size changes, and connection pooling—so you can pick the right one for your workload. Each approach solves different problems, and choosing wrong can waste hours or create new performance issues.

Understanding Why MySQL Drops Connections

MySQL doesn't keep connections open forever. After wait_timeout seconds of inactivity, the server closes the connection to free up resources. The default is 28800 seconds (8 hours), which sounds generous until you realize a web application might hold a connection between page loads.

Packet size limits are the other common trigger. The max_allowed_packet setting defaults to 64MB in MySQL 8.0. If your query or result set exceeds this—common with BLOB fields, large JOINs, or batch inserts—MySQL terminates the connection immediately.

Network issues matter too. A firewall that drops idle TCP connections after 5 minutes will cut off MySQL before wait_timeout expires. Some cloud load balancers and NAT gateways have their own timeout rules that override MySQL's settings entirely.

Server restarts produce this error as well, though the message is identical. Check your MySQL error log at /var/log/mysql/error.log (or equivalent) to see if the server actually crashed or restarted during the connection failure.

Solution Comparison: Timeout Adjustments vs Packet Size vs Pooling

Here's the side-by-side breakdown. Each fix targets a different root cause, and applying the wrong one won't help.

  • **Increase wait_timeout**: Best for batch scripts, cron jobs, or admin tools that run long queries with pauses between them. Set it in /etc/my.cnf under [mysqld]: wait_timeout = 1800 (30 minutes). Restart MySQL with systemctl restart mysql. Risk: More idle connections consume memory; each connection holds buffers even when inactive. Not a fix for web apps that should be closing connections properly.
  • **Increase max_allowed_packet**: Required when you insert or retrieve large BLOB/TEXT data, import dumps, or run queries that return huge result sets. Set max_allowed_packet = 128M in /etc/my.cnf and restart. Risk: Memory usage scales with connection count—100 connections at 128MB means up to 12.8GB potential allocation. Monitor with mysqladmin status after changes.
  • **Use interactive_timeout separately**: This controls connections opened with CLIENT_INTERACTIVE flag (mysql CLI, some GUI tools). Set it higher than wait_timeout if admin sessions drop during long investigations: interactive_timeout = 3600. Most application libraries don't use this flag, so it won't fix app-level errors.
  • **Implement connection pooling**: The correct fix for web applications. Libraries like HikariCP (Java), SQLAlchemy (Python), or Sequelize (Node.js) keep connections alive by sending periodic pings. Pool settings like maxIdleTime and testOnBorrow prevent stale connections from being used. Trade-off: Requires code changes and adds complexity to deployment, but eliminates timeout issues entirely.
  • **Adjust server net_read_timeout and net_write_timeout**: These control how long MySQL waits for data during an active query (default 30 seconds). Increase only if legitimate queries take longer: net_read_timeout = 120. Don't confuse these with wait_timeout—they apply during transmission, not idle periods.

Step-by-Step Troubleshooting Workflow

Start by identifying which scenario you're in. Connect to MySQL and run SHOW VARIABLES LIKE '%timeout%'; and SHOW VARIABLES LIKE 'max_allowed_packet';. Write down the current values—you'll need a rollback plan if changes cause problems.

Check your application logs for the exact timing of the error. If it happens after a predictable idle period (say, 8 hours between nightly batch runs), it's a wait_timeout issue. If it occurs mid-query with large data, it's packet size. Random failures under load suggest connection pool exhaustion or network problems.

For timeout issues, calculate how long connections actually need to stay open. A PHP script that runs for 10 minutes should have wait_timeout set to at least 900 seconds, with buffer room. Edit /etc/my.cnf, add or modify the value under [mysqld], then restart: systemctl restart mysql. Test with a script that deliberately idles beyond the old timeout.

For packet size problems, estimate your largest query or result set. A table with 50MB BLOB entries needs max_allowed_packet above 50MB, plus overhead for query structure. Set it to 128MB, restart, and test your import or query. Watch memory usage with top or htop during the test—if resident memory spikes dangerously, you've set it too high for your server's RAM.

When Connection Pooling Is the Right Answer

Web applications shouldn't be increasing timeouts. They should be managing connections properly.

A connection pool maintains a set of open connections and reuses them for each request. Between requests, the pool sends keepalive queries (SELECT 1) to prevent idle timeouts. Most modern frameworks include pooling—you just need to configure it. In Python's SQLAlchemy, set pool_pre_ping=True to test connections before use. In Java HikariCP, configure maxLifetime below MySQL's wait_timeout.

The trade-off is complexity. You need to tune pool size (too small causes request queuing, too large overwhelms MySQL), handle pool exhaustion errors, and ensure connections are returned after use. Connection leaks—where code forgets to close a connection—become critical bugs instead of slow memory leaks.

For single-user scripts or admin tools, pooling is overkill. Just increase wait_timeout to match your script's runtime. For production web apps serving thousands of requests per hour, pooling is the only sustainable fix. Timeout increases just mask the underlying problem of holding connections open unnecessarily.

Testing Configuration Changes Safely

Never apply MySQL configuration changes directly to production. Set up a staging server with identical MySQL version and similar load patterns. Copy your /etc/my.cnf, apply the changes, restart, and run your application's test suite.

Use MySQL's session-level settings for quick testing without a restart. Connect and run SET SESSION wait_timeout = 600; to test a new timeout value for that connection only. If it works, then make it permanent in my.cnf. The session value resets when you disconnect.

Monitor key metrics before and after changes. Run SHOW STATUS LIKE 'Threads_connected'; to watch active connections. Check SHOW STATUS LIKE 'Aborted_connects'; for failed connection attempts—a spike suggests your limits are too restrictive. Use mysqladmin extended-status | grep -i memory to track memory consumption.

  • Baseline test: Record normal memory usage, connection count, and query times before changes
  • Load test: Use a tool like sysbench or your app's load testing framework to simulate peak traffic with new settings
  • Soak test: Let the server run with new settings for at least 24 hours to catch slow memory leaks or connection buildup
  • Rollback plan: Keep the original my.cnf as my.cnf.bak and document the exact steps to revert, including the restart command

Advanced Troubleshooting When Standard Fixes Fail

Sometimes you've increased timeouts and packet sizes, but the error persists. Check for network equipment between your app and MySQL that enforces its own timeouts. AWS NLB drops idle connections after 350 seconds by default; you need to send keepalive traffic more frequently or switch to connection draining.

Firewall rules on the MySQL server can interfere. Run iptables -L -n -v or firewall-cmd --list-all to see connection tracking settings. Some firewalls drop established connections after a timeout even if MySQL considers them active. You might need to adjust conntrack timeout values with sysctl.

DNS resolution failures cause connection drops that look like timeout errors. If your app connects to MySQL via hostname, a DNS timeout or failure forces reconnection, which fails with 'server has gone away' even though MySQL is running fine. Switch to IP address in the connection string to test.

Finally, check if MySQL itself is hitting resource limits. Run SHOW PROCESSLIST; to see active connections and queries. If you're at max_connections, new connections fail immediately. Check SHOW STATUS LIKE 'Max_used_connections'; against your max_connections setting. If they're equal, you need to increase the limit or fix connection leaks in your application.

Quick troubleshooting checklist

  • Check MySQL error log for connection timeout or packet size messages
  • Verify current wait_timeout and max_allowed_packet values with SHOW VARIABLES
  • Test configuration changes in a non-production environment first
  • Monitor memory and CPU usage after applying new limits
  • Implement connection pooling if your application framework supports it
  • Set up query logging to identify slow or oversized operations
  • Document the baseline values before making changes

FAQ

What causes the MySQL server has gone away error?

MySQL closes the connection after it sits idle longer than wait_timeout (default 8 hours), when a query packet exceeds max_allowed_packet (default 64MB), or when the server restarts. Network interruptions and firewall rules that drop idle TCP connections also trigger this error.

Should I increase wait_timeout or use connection pooling?

Use connection pooling for web applications because it reuses connections efficiently and prevents timeout issues without holding MySQL resources. Increase wait_timeout only for batch scripts or cron jobs that run long queries, setting it between 600-1800 seconds rather than disabling it entirely.

Is it safe to increase max_allowed_packet to 256MB?

Yes, if you regularly process large queries or BLOB data, but monitor memory usage because MySQL allocates this per connection. Start with 128MB, test under load, then adjust. Each connection can potentially use the full packet buffer, so 100 connections at 256MB could theoretically require 25GB of RAM.