PDOException: SQLSTATE[HY000] [2006] MySQL server has gone away in /var/www/app/src/Database/Connection.php:42
ID: php/pdo-mysql-server-has-gone-away
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| PHP 7.4 | active | — | — | — |
| PHP 8.1 | active | — | — | — |
| PHP 8.2 | active | — | — | — |
| MySQL 5.7 | active | — | — | — |
| MySQL 8.0 | active | — | — | — |
Root Cause
The MySQL server closed the connection due to a timeout (wait_timeout or interactive_timeout), a packet size exceeding max_allowed_packet, or a server crash/restart, and the PHP PDO connection was not re-established.
generic中文
MySQL服务器因超时(wait_timeout或interactive_timeout)、数据包大小超过max_allowed_packet或服务器崩溃/重启而关闭连接,且PHP PDO连接未重新建立。
Official Documentation
https://dev.mysql.com/doc/refman/8.0/en/gone-away.htmlWorkarounds
-
75% success Increase MySQL's wait_timeout and interactive_timeout in my.cnf, e.g., set wait_timeout=28800; interactive_timeout=28800. Then restart MySQL.
Increase MySQL's wait_timeout and interactive_timeout in my.cnf, e.g., set wait_timeout=28800; interactive_timeout=28800. Then restart MySQL.
-
70% success Increase max_allowed_packet in my.cnf to handle large queries, e.g., set max_allowed_packet=64M. Restart MySQL.
Increase max_allowed_packet in my.cnf to handle large queries, e.g., set max_allowed_packet=64M. Restart MySQL.
-
90% success Implement connection retry logic in PHP: catch the exception and reconnect using a new PDO instance. Example: try { $stmt = $pdo->query('SELECT 1'); } catch (\PDOException $e) { if ($e->getCode() == 2006) { $pdo = new PDO($dsn, $user, $pass); $stmt = $pdo->query('SELECT 1'); } }
Implement connection retry logic in PHP: catch the exception and reconnect using a new PDO instance. Example: try { $stmt = $pdo->query('SELECT 1'); } catch (\PDOException $e) { if ($e->getCode() == 2006) { $pdo = new PDO($dsn, $user, $pass); $stmt = $pdo->query('SELECT 1'); } }
中文步骤
Increase MySQL's wait_timeout and interactive_timeout in my.cnf, e.g., set wait_timeout=28800; interactive_timeout=28800. Then restart MySQL.
Increase max_allowed_packet in my.cnf to handle large queries, e.g., set max_allowed_packet=64M. Restart MySQL.
Implement connection retry logic in PHP: catch the exception and reconnect using a new PDO instance. Example: try { $stmt = $pdo->query('SELECT 1'); } catch (\PDOException $e) { if ($e->getCode() == 2006) { $pdo = new PDO($dsn, $user, $pass); $stmt = $pdo->query('SELECT 1'); } }
Dead Ends
Common approaches that don't work:
-
70% fail
The error is caused by MySQL's timeout, not PHP's execution time; changing PHP settings does not prevent the server from closing idle connections.
-
50% fail
Persistent connections can mask the issue but may lead to stale connections being reused, causing the same error later; they also consume server resources.
-
80% fail
Restarting temporarily reopens connections, but the underlying timeout or packet size issue remains, causing the error to recur.