MySQL ERROR 2006 "server has gone away" occurs when the database connection is lost or closed unexpectedly. This happens when idle connections exceed the timeout threshold (default 8 hours), the server is restarted, packets are too large, or network issues disconnect the client. The error indicates the connection was valid but is no longer available.
MySQL ERROR 2006 "server has gone away" (HY000) indicates that your application had a valid connection to the MySQL server, but that connection was lost or closed before the query was executed. Unlike authentication errors that fail immediately, this error occurs on an established connection that drops unexpectedly. The error can manifest in different scenarios: - **Connection timeout**: Idle connection dropped due to server's wait_timeout setting (default 8 hours) - **Server restart**: MySQL server was restarted while client maintained stale connection - **Packet size exceeded**: Query or data packet larger than max_allowed_packet (default 64MB) - **Network disconnection**: Network issue severed the TCP/IP connection between client and server - **Firewall blocking**: Firewall closed the connection due to inactivity - **Server overload**: Server crashed, hung, or became unresponsive due to resource constraints - **Killed connection**: Administrator killed the connection with KILL command - **Forked processes**: Child processes in multithreaded application reusing parent's connection This error is particularly common in long-running processes, application servers with connection pooling, or batch jobs that have idle periods between queries.
The most important first step is confirming the server is actually online and responsive. A "gone away" error could indicate the server crashed or stopped.
Check MySQL service status:
# Linux - check service
sudo systemctl status mysql
# macOS - check if running
brew services list | grep mysql
# Windows - check Services
sc query MySQL80
# Or check if port is listening
sudo netstat -tulpn | grep 3306
sudo ss -tulpn | grep 3306If MySQL is not running, start it:
# Linux
sudo systemctl start mysql
# macOS with Homebrew
brew services start mysql
# Windows service
net start MySQL80
# Or direct command
mysqld_safe &Once running, test basic connectivity:
# Test simple connection
mysql -u root -p -h localhost -e "SELECT 1;"
# If this succeeds, server is responsive
# If it fails, check error logs:
tail -f /var/log/mysql/error.logCheck for recent restarts or crashes:
# View MySQL error log for crashes
tail -100 /var/log/mysql/error.log | grep -i "crash|start|ready"
# Check system logs for MySQL events
sudo journalctl -u mysql -n 50 --no-pagerThe most common cause is the connection being idle longer than wait_timeout (default 28800 seconds = 8 hours). Increase this limit to prevent automatic disconnection.
Check current timeout values:
mysql -u root -p -e "SHOW VARIABLES LIKE '%timeout%';"You'll see output like:
+-----------+--------+
| Variable_name | Value |
+-----------+--------+
| connect_timeout | 10 |
| interactive_timeout | 28800 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| wait_timeout | 28800 |
+-----------+--------+Increase wait_timeout permanently by editing MySQL configuration:
On Linux/Mac:
# Edit my.cnf or mysqld.cnf
sudo nano /etc/mysql/my.cnf
# or
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnfFind [mysqld] section and add/update:
[mysqld]
wait_timeout = 864000
interactive_timeout = 864000
net_read_timeout = 30
net_write_timeout = 60For Windows, edit:
C:\ProgramData\MySQL\MySQL Server 8.0\my.iniAfter editing, restart MySQL:
# Linux
sudo systemctl restart mysql
# macOS
brew services restart mysql
# Windows
net stop MySQL80
net start MySQL80Or set temporarily (until restart):
# Connect as root
mysql -u root -p -e "SET GLOBAL wait_timeout = 864000; SET GLOBAL interactive_timeout = 864000;"
# Verify changes
mysql -u root -p -e "SHOW VARIABLES LIKE '%timeout%';"Note: Set wait_timeout to a reasonable value based on your application. Common values:
- 300 seconds (5 minutes) - for web apps with frequent requests
- 3600 seconds (1 hour) - for batch jobs
- 86400 seconds (1 day) - for long-running processes
If you're getting "gone away" errors when sending large data (bulk inserts, large exports), increase max_allowed_packet.
Check current setting:
mysql -u root -p -e "SHOW VARIABLES LIKE 'max_allowed_packet';"Default is usually 64MB. For large operations, increase it:
Edit MySQL configuration permanently:
On Linux/Mac:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnfOn Windows:
C:\ProgramData\MySQL\MySQL Server 8.0\my.iniFind [mysqld] and add/update:
[mysqld]
max_allowed_packet = 256MAlso update the client section:
[mysqldump]
max_allowed_packet = 256M
[mysql]
max_allowed_packet = 256MRestart MySQL:
# Linux
sudo systemctl restart mysql
# macOS
brew services restart mysql
# Windows
net stop MySQL80
net start MySQL80Or set temporarily:
mysql -u root -p -e "SET GLOBAL max_allowed_packet = 268435456;" # 256MB
# Verify
mysql -u root -p -e "SHOW VARIABLES LIKE 'max_allowed_packet';"For application clients (php.ini, etc.):
; In php.ini
mysql.max_allowed_packet = 256MFor applications that have idle periods, implement automatic reconnection or connection pooling to maintain fresh connections.
PHP/MySQLi Example:
<?php
// Check if connection is alive before executing query
if (!$mysqli->ping()) {
// Reconnect if connection was lost
$mysqli->close();
$mysqli = new mysqli("localhost", "user", "password", "database");
if ($mysqli->connect_error) {
die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
}
}
// Now safe to execute query
$result = $mysqli->query("SELECT * FROM table");
?>Python/MySQL-connector Example:
import mysql.connector
from mysql.connector import Error
def get_db_connection():
try:
connection = mysql.connector.connect(
host='localhost',
user='user',
password='password',
database='database',
autocommit=True
)
return connection
except Error as e:
print(f"Error: {e}")
return None
# Before each query, check connection
connection = get_db_connection()
if not connection.is_connected():
connection = get_db_connection()
cursor = connection.cursor()
cursor.execute("SELECT 1")Node.js/mysql2 Example with Connection Pool:
const mysql = require('mysql2/promise');
const pool = mysql.createPool({
host: 'localhost',
user: 'user',
password: 'password',
database: 'database',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0,
enableKeepAlive: true,
keepAliveInitialDelayMs: 0
});
// Query with automatic reconnection
async function executeQuery(sql) {
let connection;
try {
connection = await pool.getConnection();
const [rows] = await connection.execute(sql);
return rows;
} catch (error) {
console.error('Query failed:', error);
throw error;
} finally {
if (connection) {
connection.release();
}
}
}Java/HikariCP Example:
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/database");
config.setUsername("user");
config.setPassword("password");
config.setMaximumPoolSize(10);
config.setMaxLifetime(1800000); // 30 minutes
config.setIdleTimeout(600000); // 10 minutes
HikariDataSource dataSource = new HikariDataSource(config);
// Get connection (automatically managed)
try (Connection conn = dataSource.getConnection()) {
// Execute query
}Key features to implement:
- Connection pool with configurable size
- Automatic reconnection on "gone away" errors
- Keep-alive/ping to detect stale connections
- Connection timeout and lifetime limits
- Retry logic for transient failures
Network issues or firewalls may close idle connections. Verify network connectivity and configure timeout settings.
Test network connectivity:
# Ping MySQL server
ping mysql_server_hostname
# Check if port 3306 is reachable
nc -zv mysql_server_hostname 3306
telnet mysql_server_hostname 3306
# For remote connections, test from client
mysql -h mysql_server_hostname -u user -p -e "SELECT 1;"If using SSH tunnel:
# Establish SSH tunnel on port 3307
ssh -L 3307:localhost:3306 user@mysql_server_hostname
# Connect through tunnel
mysql -h localhost -P 3307 -u user -pConfigure application timeouts:
In application code, set appropriate socket timeouts:
PHP (mysqli):
$mysqli = new mysqli("localhost", "user", "password", "database");
$mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 10);
$mysqli->options(MYSQLI_OPT_READ_TIMEOUT, 30);
$mysqli->options(MYSQLI_OPT_WRITE_TIMEOUT, 30);Python:
connection = mysql.connector.connect(
host='localhost',
user='user',
password='password',
database='database',
connection_timeout=10,
autocommit=True
)Check firewall rules:
# Linux - check firewall rules for MySQL
sudo iptables -L -n | grep 3306
sudo ufw status | grep 3306
# macOS - check pf rules
sudo pfctl -s rules | grep 3306If behind corporate firewall or proxy:
- Ask network team to whitelist MySQL port
- Increase session idle timeout on proxy
- Use connection pooling with keep-alive
- Consider using SSH tunnel if direct access is blocked
Disk full or resource exhaustion can cause MySQL to become unresponsive, resulting in "gone away" errors.
Check disk space:
# Check all mounted filesystems
df -h
# Check specifically MySQL data directory
du -sh /var/lib/mysql
du -sh /var/lib/mysql/*
# Look for nearly-full partitions (>90% full)
df -h | awk '$5 > 80 { print "WARNING: " $0 }'Free up disk space if needed:
# Find large files
find /var/lib/mysql -size +1G -type f
# Check binary logs (can grow large)
ls -lh /var/log/mysql/*
# Archive old binary logs
# First check retention settings
mysql -u root -p -e "SHOW BINARY LOGS;"
mysql -u root -p -e "SHOW VARIABLES LIKE 'expire_logs_days';"
# Purge old binary logs (e.g., older than 7 days)
mysql -u root -p -e "PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);"Monitor server memory:
# Check memory usage
free -h
# Check MySQL memory usage specifically
ps aux | grep mysqld | head -1
# Or
top -b -n 1 | grep mysqld
# Check if OOM killer is active
grep -i "out of memory" /var/log/syslog
dmesg | grep -i "killed process"Check MySQL process limits:
# Get MySQL PID
pgrep mysqld
# Check open files and limits
# If mysqld PID is 1234:
cat /proc/1234/limits
# May need to increase max_connections or other limits
mysql -u root -p -e "SHOW VARIABLES LIKE 'max_connections';"
mysql -u root -p -e "SHOW VARIABLES LIKE 'table_open_cache';"Monitor in real-time:
# Use iostat to watch disk I/O
iostat -x 1
# Use top to watch processes
top
# Use htop for better interface
htopReview MySQL error log for clues:
tail -100 /var/log/mysql/error.log | grep -i "error|warning|unable"Corrupted or crashed tables can cause MySQL to close connections. Check and repair tables if needed.
Identify corrupted tables:
# Check all tables in database
mysql -u root -p -e "CHECK TABLE database_name.*;"
# Or check individual table
mysql -u root -p database_name -e "CHECK TABLE table_name;"
# Check with extended option for more thorough check
mysql -u root -p database_name -e "CHECK TABLE table_name EXTENDED;"
# Check multiple tables
mysql -u root -p database_name -e "CHECK TABLE table1, table2, table3;"Look for "error" in the output, like:
Table: database.table_name Op: check Status: errorRepair corrupted tables:
# Repair single table
mysql -u root -p database_name -e "REPAIR TABLE table_name;"
# Repair with options
mysql -u root -p database_name -e "REPAIR TABLE table_name QUICK;"
mysql -u root -p database_name -e "REPAIR TABLE table_name EXTENDED;"
# Repair multiple tables
mysql -u root -p database_name -e "REPAIR TABLE table1, table2, table3;"Using myisamchk tool (for MyISAM tables):
# Stop MySQL first
sudo systemctl stop mysql
# Check table
myisamchk /var/lib/mysql/database_name/table_name.MYI
# Repair table
myisamchk -r /var/lib/mysql/database_name/table_name.MYI
# Restart MySQL
sudo systemctl start mysqlOptimize after repair:
# After repair, optimize the table
mysql -u root -p database_name -e "OPTIMIZE TABLE table_name;"
# Check again to confirm
mysql -u root -p database_name -e "CHECK TABLE table_name;"InnoDB table recovery:
If using InnoDB and repair fails:
# Set recovery mode and restart
mysql -u root -p -e "SET GLOBAL innodb_force_recovery = 4;"
# Restart MySQL to rebuild tables
sudo systemctl restart mysql
# Then reset recovery mode
mysql -u root -p -e "SET GLOBAL innodb_force_recovery = 0;"Multithreaded or multi-process applications (especially those using fork()) can reuse connections inappropriately, causing "gone away" errors.
For PHP applications with forking:
<?php
// WRONG - reusing parent connection in child process
$mysqli = new mysqli("localhost", "user", "password", "database");
foreach ($items as $item) {
$pid = pcntl_fork();
if ($pid == 0) {
// Child process reusing parent's connection
$result = $mysqli->query("SELECT * FROM table");
exit();
}
}
// CORRECT - establish new connection in child
foreach ($items as $item) {
$pid = pcntl_fork();
if ($pid == 0) {
// Child process gets its own connection
$child_db = new mysqli("localhost", "user", "password", "database");
$result = $child_db->query("SELECT * FROM table");
$child_db->close();
exit();
}
}For Python applications with multiprocessing:
# WRONG - reusing connection across processes
import mysql.connector
from multiprocessing import Pool
db = mysql.connector.connect(
host="localhost",
user="user",
password="password",
database="database"
)
def process_item(item):
cursor = db.cursor() # Reused connection across processes
cursor.execute("SELECT * FROM table")
return cursor.fetchall()
# CORRECT - each process gets its own connection
def process_item_correct(item):
db_local = mysql.connector.connect(
host="localhost",
user="user",
password="password",
database="database"
)
cursor = db_local.cursor()
cursor.execute("SELECT * FROM table")
result = cursor.fetchall()
db_local.close()
return result
if __name__ == '__main__':
with Pool(processes=4) as pool:
results = pool.map(process_item_correct, items)For Node.js worker threads:
// WRONG - sharing connection pool across threads
const pool = mysql.createPool({ /* config */ });
worker.on('message', async (msg) => {
const conn = await pool.getConnection();
// This can cause issues with connection state
});
// CORRECT - each worker gets its own pool
const { Worker } = require('worker_threads');
const worker = new Worker('./worker.js');
// Worker creates its own pool internallyGeneral guidelines:
- Each process/thread should have its own database connection
- Never share connection objects across process/thread boundaries
- Use connection pooling libraries that handle this automatically
- Test with multiple concurrent processes to find issues
- Monitor connection count to detect connection leaks
MySQL Connection Lifecycle and Error Scenarios:
When a client connects to MySQL, several states can lead to "gone away" errors:
1. Valid Connection Drops: The connection was established but is no longer available. This differs from connection errors that fail immediately.
2. Timeout Types:
- wait_timeout: Closes idle connection (default 28800s = 8 hours)
- interactive_timeout: For interactive clients (default 28800s)
- net_read_timeout: Max time waiting for data (default 30s)
- net_write_timeout: Max time sending data (default 60s)
3. TCP Connection State: Network-level disconnections don't immediately notify the application. A "gone away" error occurs when the application tries to use a stale connection.
4. Packet Size Limits:
- max_allowed_packet (default 64MB) applies to individual queries and prepared statements
- When exceeded, server closes connection
- Includes both upload and download data (INSERT, SELECT with large results)
5. Connection Pool Anti-Patterns:
- Connections don't survive server restart
- Idle pooled connections may timeout before being reused
- Connections closed by server but not reported to pool until used
- Child processes inheriting parent's file descriptors (TCP socket) causes issues
6. Firewall and Proxy Behaviors:
- Network proxies may close idle connections after inactivity timeout
- Firewalls may silently drop idle connections
- NAT timeouts can cause similar symptoms
- TCP keep-alive settings (TCP_KEEPALIVE) help prevent this
7. Server Resource Impact:
- Out of memory can cause mysqld process to be killed by OS
- Full disk may prevent query execution, causing connection closure
- Too many connections can exhaust connection pool
- Table locks or long queries may appear as "gone away"
8. Platform-Specific Considerations:
Linux:
- Check TCP keep-alive: cat /proc/sys/net/ipv4/tcp_keepalive_time
- SELinux policies may restrict MySQL connections
- Container restart policies affect connection state
macOS:
- Homebrew MySQL service restarts may drop connections
- FileVault encryption can impact disk I/O, causing timeouts
- System sleep/wake affects socket state
Windows:
- Service restart doesn't gracefully close connections
- Windows Firewall may close idle TCP connections
- UAC elevation may affect MySQL service startup
9. Diagnosis Approach:
- Check server logs: /var/log/mysql/error.log
- Monitor connections: SHOW PROCESSLIST
- Check variables: SHOW VARIABLES LIKE 'timeout%'
- Monitor disk/memory: df -h, free -h
- Test simple ping: SELECT 1
10. Application-Level Solutions:
- Connection pooling with health checks
- Automatic reconnection on "gone away"
- Exponential backoff for retry logic
- Keep-alive queries for idle periods
- Dedicated connection per thread/process
Connection Keep-Alive Pattern:
-- Execute simple ping query periodically
SELECT 1;
-- Or use connection pooling library with keep-alive
-- Most modern libraries (HikariCP, sqlalchemy, etc.) have built-in keep-aliveMonitoring and Alerting:
# Monitor current connections
WATCH -n 5 'mysql -u root -p -e "SHOW PROCESSLIST;"'
# Count connections by user
mysql -u root -p -e "SELECT USER(), COUNT(*) FROM information_schema.PROCESSLIST GROUP BY USER();"
# Monitor slow queries that might cause timeouts
SHOW VARIABLES LIKE 'slow_query_log%';
SHOW VARIABLES LIKE 'long_query_time';Prevention Checklist:
□ Set appropriate wait_timeout based on application needs
□ Set max_allowed_packet larger than largest query/data
□ Implement connection pooling with health checks
□ Add ping/reconnect logic before queries
□ Monitor disk space and server resources
□ Test application with server restart scenarios
□ Verify firewall allows persistent connections
□ Check for corrupted tables regularly
□ Monitor MySQL error log for warnings
□ Use connection keep-alive in long-running processes
□ Test multiprocess/multithreaded code with separate connections
EE_WRITE (3): Error writing file
How to fix "EE_WRITE (3): Error writing file" in MySQL
CR_PARAMS_NOT_BOUND (2031): No data supplied for parameters
How to fix "CR_PARAMS_NOT_BOUND (2031): No data supplied for parameters" in MySQL
CR_DNS_SRV_LOOKUP_FAILED (2070): DNS SRV lookup failed
How to fix "CR_DNS_SRV_LOOKUP_FAILED (2070): DNS SRV lookup failed" in MySQL
ERROR 1146: Table 'database.table' doesn't exist
How to fix "ERROR 1146: Table doesn't exist" in MySQL
ERROR 1040: Too many connections
How to fix "ERROR 1040: Too many connections" in MySQL