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

On this page
- Understanding Why MySQL Drops Connections
- Solution Comparison: Timeout Adjustments vs Packet Size vs Pooling
- Step-by-Step Troubleshooting Workflow
- When Connection Pooling Is the Right Answer
- Testing Configuration Changes Safely
- Recommended Approach by Use Case
- Advanced Troubleshooting When Standard Fixes Fail
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
Recommended Approach by Use Case
Here's my recommendation matrix based on what actually works in production environments.
- **High-traffic web application**: Implement connection pooling with pool_size matching your typical concurrent request count. Set testOnBorrow or pool_pre_ping to true. Set wait_timeout to 600 seconds as a safety net, but don't rely on it. This prevents 95% of timeout errors without wasting MySQL resources.
- **Nightly batch job or ETL script**: Increase wait_timeout to 1800-3600 seconds (30-60 minutes) depending on job duration. Also set max_allowed_packet to 128M if processing large datasets. No need for connection pooling in a single-threaded script.
- **WordPress or similar PHP app without built-in pooling**: Set wait_timeout to 300 seconds (5 minutes) to match typical user session lengths. Use a plugin that properly closes database connections after each request. Consider migrating to a framework that supports pooling if connection errors persist.
- **Database import/export operations**: Increase max_allowed_packet to 256M or higher for mysqldump operations. Set net_read_timeout and net_write_timeout to 600 seconds for slow network scenarios. Reset these after the import completes to avoid leaving the server with inflated limits.
- **Microservices with many short-lived connections**: Use connection pooling with aggressive maxLifetime (30-60 seconds) to force pool refresh. Set wait_timeout to 120 seconds to quickly reclaim resources from crashed or zombie services. Monitor connection churn with Aborted_connects metric.
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.
Related articles
- Hosting OperationsSelf-Hosted App Deployment Fails? Check DNS, SSL, Reverse Proxy, and Logs FirstTroubleshoot failed self-hosted app deployments by checking DNS, SSL, reverse proxy routing, container status, logs, and ports.
- Hosting OperationsSelf-Hosted PaaS on a VPS: What to Check Before Installing Coolify, Dokploy, or CapRoverA hosting support checklist for preparing a VPS before installing self-hosted PaaS tools like Coolify, Dokploy, or CapRover.
- Hosting OperationsLinux Server Security Lessons from the Arch Linux Malware Package IncidentPractical Linux server security checklist for VPS admins after package malware concerns, with safe checks, rollback steps, and support guidance.
- Hosting OperationsAWS Lightsail Hong Kong VPS Latency: Practical Hosting Guide for IndonesiaLearn how to test AWS Lightsail Hong Kong VPS latency, compare regions, migrate safely, and troubleshoot hosting performance.
- Hosting OperationsCloudflare Tomorrow Watchlist: A Practical Hosting Operations GuidePractical Cloudflare troubleshooting checklist for DNS, SSL, caching, WAF, origin health, safe testing, and rollback planning.
- Hosting OperationsNetwork Safety Checklist for AI Agent Skills in Hosting OperationsAudit AI agent skills safely with network checks, secret protection, sandbox testing, rollback steps, and hosting support troubleshooting guidance.