Symfony 3.4出现“2006 MySQL server has gone away”错误求助
Let's tackle this frustrating issue where your Symfony 3.4 app throws a "MySQL server has gone away" error after being idle, then works fine again for a while. This typically happens because Doctrine holds onto a database connection that MySQL has already closed due to inactivity—even with your high wait_timeout setting, there are a few key fixes to implement:
1. Enable Doctrine Auto-Reconnect & Connection Pinging
First, update your Doctrine DBAL configuration in app/config/config.yml to tell Doctrine to automatically check and reestablish broken connections:
doctrine: dbal: default_connection: default connections: default: # Keep your existing database config (driver, host, dbname, user, password) auto_reconnect: true options: !php/const PDO::ATTR_PING: true
auto_reconnecttells Doctrine to attempt reconnection if it detects a dead connection.PDO::ATTR_PINGmakes PDO check if the connection is alive before executing any query—if it's dead, it'll reconnect automatically.
2. Verify interactive_timeout in MySQL
You've set wait_timeout to 328800 seconds, but MySQL also has an interactive_timeout setting that affects connections from interactive clients. While PHP usually uses non-interactive connections, it's worth checking if this value is lower than wait_timeout:
Run these commands in your MySQL console:
SHOW VARIABLES LIKE 'interactive_timeout';
If the value is less than 328800, update it to match your wait_timeout and restart MySQL:
SET GLOBAL interactive_timeout = 328800;
Don't forget to add this to your MySQL config file (like my.cnf or my.ini) to make the change permanent.
3. Configure Doctrine Connection Pool Idle Timeout
Symfony 3.4's Doctrine integration lets you set an idle timeout for the connection pool, which ensures idle connections are recycled before MySQL can drop them:
Add this to your Doctrine DBAL config:
doctrine: dbal: connections: default: # Existing config pool: min_connections: 1 max_connections: 10 idle_timeout: 300 # 5 minutes—adjust based on your app's idle periods
This setting tells the pool to close any connection that's been idle for 300 seconds, so the next request will get a fresh connection instead of a dead one.
4. Fallback: Manual Reconnection in Code
As a safety net, you can catch the specific exception and manually reconnect in your controllers or services:
use Doctrine\DBAL\Driver\PDOException; use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException; // Inside your controller method or service try { // Your database operation (e.g., fetching entities, running queries) $entities = $this->getDoctrine()->getRepository(YourEntity::class)->findAll(); } catch (PDOException $e) { if (strpos($e->getMessage(), 'MySQL server has gone away') !== false) { // Close the dead connection and reconnect $connection = $this->getDoctrine()->getConnection(); $connection->close(); $connection->connect(); // Retry your database operation once $entities = $this->getDoctrine()->getRepository(YourEntity::class)->findAll(); } else { // Re-throw other PDO exceptions as a service unavailable error throw new ServiceUnavailableHttpException(null, $e->getMessage(), $e); } }
Quick Notes for Your Environment
Since you're using PHP 5.6 and MySQL 5.6, make sure your Doctrine DBAL version is compatible with Symfony 3.4—stick to versions ~2.5 or ~2.6 (check your composer.json to confirm). Older versions might have bugs with connection handling that these fixes address.
内容的提问来源于stack exchange,提问作者Sameh Serag

