MySQL 2006: MySQL server has gone away fix
MySQL throws 2006 when the server closes the connection mid-query. Usually from timeout, oversized packets, or server restart.
Quick answer
Increase max_allowed_packet to 64M or more, and raise wait_timeout and interactive_timeout to 28800 in my.cnf, then restart MySQL. If it still breaks, your server is crashing under load or someone's killing the connection.
What's actually happening here
MySQL error 2006 means the server closed the connection before your query finished. The server doesn't send a goodbye—it just drops you. Three things cause this:
- Packet too large – MySQL has a default limit of 4MB or 16MB (depends on version) for any single packet. Blob columns, large JSON inserts, or stored procedures returning big resultsets will blow past this. MySQL kills the connection without warning.
- Timeout – The server's
wait_timeout(default 28800 seconds for interactive, 60 seconds for non-interactive) kills idle connections. Long-running scripts that pause between queries hit this. - Server crash or restart – MySQL went down and back up. Your client still holds the old connection handle. Next query fails.
I've seen this most frequently when someone runs an INSERT ... SELECT that moves terabytes of data, or a cron job that runs a heavy UPDATE every 5 minutes and the server's innodb_buffer_pool runs dry. The error message is sparse, but the fix path is clear.
Fix steps – in order of likelihood
- Check MySQL error log –
tail -100 /var/log/mysql/error.log(or/var/log/mysqld.logon RHEL). Look forAborted connection,Too many connections, orOut of memory. If you see a memory error, skip packet size—your server needs more RAM or query optimization. - Bump max_allowed_packet – Open
/etc/mysql/my.cnfor/etc/my.cnfand set:
Restart:[mysqld] max_allowed_packet=64Msystemctl restart mysql. Test withSHOW VARIABLES LIKE 'max_allowed_packet';If you're on MariaDB, same variable name. For AWS RDS, set via parameter group. - Raise timeouts – Add these under
[mysqld]:
28800 seconds = 8 hours. Adjust to your needs. If you have persistent connections (PHP's PDO withwait_timeout=28800 interactive_timeout=28800ATTR_PERSISTENT), non-interactive clients usewait_timeout, interactive ones useinteractive_timeout. - Check for server restarts – Run
uptimeon the MySQL host. If the server came up recently, checkgrep -i 'restart' /var/log/mysql/error.log. If MySQL keeps crashing, you're probably hittingOut of memoryfrom large joins or insufficient swap. Addinnodb_buffer_pool_size = 70% of RAM(e.g., 14GB on 20GB machine) andtmp_table_size = 64M. - Verify network stability – If MySQL is remote, check
netstat -s | grep reset. TCP resets from firewalls or load balancers can drop connections mid-query. Addtcp_keepalive_time = 600to/etc/sysctl.conf.
Alternative fixes – when the main ones fail
- PHP specifically – In PDO, set
PDO::ATTR_EMULATE_PREPARES = falseand catch2006errors with a reconnect loop:
This isn't ideal – you're masking a systemic problem. Fix the root cause first.try { $pdo->query('SELECT 1'); } catch (PDOException $e) { if ($e->getCode() == 2006) { $pdo = new PDO($dsn, $user, $pass); } } - Python / SQLAlchemy – Use
pool_pre_ping=Trueincreate_engine(). It tests connections before handing them out. If the test fails, it opens a new one. Reduces but doesn't eliminate the error. - For large inserts (blobs, JSON) – Split your data into chunks of 1MB each and insert in a loop. MySQL can handle multiple small packets better than one huge one. Example with 1000 rows per
INSERT.
Prevention tip – what I do in production
Set max_allowed_packet to 64MB before you ever need it. It costs you nothing. For timeouts, use wait_timeout=3600 (1 hour) on web apps—long enough for most queries, short enough to free connections from dead scripts. Use connection pooling (ProxySQL, PgBouncer for MySQL) to reuse connections and avoid handshake costs. Monitor Aborted_connects and Aborted_clients in SHOW GLOBAL STATUS – they're early warning signs. And for the love of databases, never run a production MySQL on a machine with less than 2GB of RAM if you're doing anything beyond a toy app.
Was this solution helpful?