Bali, Indonesia
Insights

MySQL Server Has Gone Away During Import: max_allowed_packet or wait_timeout?

October 26, 2026
0:00
You start importing a database dump, it runs for a while, then stops with ERROR 2006 (HY000): MySQL server has gone away or its close relative ERROR 2013 (HY000): Lost connection to MySQL server during query. The usual advice is to raise max_allowed_packet and wait_timeout together and try again. Sometimes that works, but it hides which limit actually tripped. One of the most common causes is neither setting: the MySQL process itself died and restarted halfway through. This guide is about collecting evidence first. Each cause leaves different traces, and you can check all of them from the command line in a few minutes.
"Gone away" is a client-side message. It means the client tried to use a connection and found that the other end had closed it. It says nothing about why. The connection can disappear for several reasons:
  1. The server rejected a statement because it was bigger than max_allowed_packet and closed the connection.
  2. The connection sat idle longer than wait_timeout, and the server dropped it.
  3. mysqld crashed or was killed, often by the kernel's OOM killer (the out-of-memory killer, which terminates a process when RAM and swap run out), and the client lost its connection along with everything else.
  4. Something in between, such as a proxy or firewall, cut the connection.
In support work, the first question worth asking is not "which variable is too small" but "did the server restart?" If it did, raising packet or timeout limits changes nothing. The next import will fail at roughly the same point.
Run these checks right after the failure, before anyone restarts anything:
BASH
# Uptime in seconds. If it is shorter than the import ran, mysqld restarted mid-import.
mysqladmin status

# Where the server writes its error log
mysql -N -e 'SELECT @@log_error'

# Kernel messages about OOM kills in the last few hours
journalctl -k --since '3 hours ago' | grep -iE 'out of memory|killed process'

# Service state and recent restarts (service name may be mysql, mysqld, or mariadb)
systemctl status mysql
If Uptime is only a few minutes and the kernel log shows Killed process with mysqld or mariadbd in it, you have your answer. The import pushed memory over the edge, or something else on the box did and MySQL was the process the kernel chose. Why the kernel tends to pick MySQL over processes that look hungrier is covered in Kenapa OOM Killer Mematikan MySQL, Bukan Proses yang Paling Boros Memori. If there is no OOM message but uptime is still short, open the error log path from the second command and read the last lines before the restart. A crash usually leaves a stack trace or an assertion message there. A clean restart from a cron job or a panel action looks like a normal shutdown sequence. If uptime is long and there is no kill in the kernel log, the server stayed up and closed the connection on purpose. That points to the two limits in the title.
MySQL sends each statement to the server as a single packet. A dump made with mysqldump uses extended inserts by default: one INSERT statement carries many rows at once. One of those lines can easily reach tens of megabytes, especially for tables with BLOB or long TEXT columns, or tables full of serialized data like WordPress options or page builder content. The limit exists on both sides. The server has its own max_allowed_packet, and so does the client doing the import. Either one can reject the statement. Compare what the server allows with the largest statement in the file:
BASH
# Server-side limits, in bytes and seconds
mysql -N -e 'SELECT @@global.max_allowed_packet, @@global.wait_timeout, @@global.interactive_timeout, @@global.net_read_timeout'

# Longest line in the dump, in bytes (LC_ALL=C makes awk count bytes, not characters)
LC_ALL=C awk '{ if (length(0) > max) max = length(0) } END { print max }' dump.sql

# Same check for a gzipped dump, without unpacking it to disk
zcat dump.sql.gz | LC_ALL=C awk '{ if (length(0) > max) max = length(0) } END { print max }'
The longest line is a close approximation of the largest packet, because mysqldump writes each extended insert as one line. If that number is larger than the server's max_allowed_packet, you have found a real problem regardless of what else is going on. The error log confirms it, if the server logs aborted connections. That depends on log_error_verbosity in MySQL 8 or log_warnings in MariaDB and older MySQL, so the line might not be there on a default setup. When it is, it looks roughly like this:
TEXT
# Illustrative output format (exact wording and prefixes vary by version)
Aborted connection 1234 to db: 'shopdb' user: 'shopuser' host: 'localhost' (Got a packet bigger than 'max_allowed_packet' bytes)
Aborted connection 1240 to db: 'shopdb' user: 'shopuser' host: 'localhost' (Got timeout reading communication packets)
The text in parentheses is the useful part. "Got a packet bigger than" points to the packet limit. "Got timeout reading communication packets" points to a timeout, either wait_timeout on an idle connection or net_read_timeout when the client stopped sending in the middle of a statement.
This is where many people go wrong. wait_timeout only applies to idle connections, ones where the server is waiting for the next command. A plain mysql dbname < dump.sql import sends statements continuously, so the connection is almost never idle long enough to hit it. If the import failed on a big statement after running steadily, wait_timeout is an unlikely suspect. It becomes the real cause in a different pattern: a script that connects, does something slow without touching the database, then comes back to query. Examples include a PHP migration script that processes files or calls an external API between queries, a long cron job that holds one connection for its whole run, or a persistent connection that sits in a pool overnight. The query after the long pause hits a connection the server has already closed. You can reproduce this behavior safely in a test session. Open the mysql client, run SET SESSION wait_timeout = 10;, wait about 20 seconds, then run SELECT 1;. The client reports that the connection was lost and, by default, tries to reconnect. Keep in mind that the session value can come from interactive_timeout instead of wait_timeout for interactive clients, so check SELECT @@session.wait_timeout; from the same kind of client your script uses rather than assuming the global value applies. The evidence usually lines up like this:
EvidenceLikely cause
Short Uptime, Killed process in kernel logOOM kill of mysqld
Short Uptime, no OOM message, stack trace in error logCrash, needs separate investigation
Long uptime, longest dump line > max_allowed_packetPacket limit
Long uptime, failure after a pause in a script, timeout message in logwait_timeout (or interactive_timeout)
Long uptime, timeout message during a slow or remote pipenet_read_timeout or the network path
Once you know the cause, change only that setting, and change it in the right place. For the packet limit, SET GLOBAL max_allowed_packet = ... takes effect only for new connections, and it is lost when the server restarts. To make it permanent, set it under [mysqld] in the server config file, whose location depends on the distro and on whether a control panel manages it. Raise the client side too, for example mysql --max_allowed_packet=256M dbname < dump.sql. The value 256M here is an illustrative example. Size it to the longest line you measured plus some headroom. The protocol caps it at 1GB, and a very large value lets a single connection allocate a lot of memory, so going higher than you need is not free. On shared hosting you usually cannot touch global settings. The practical fix there is on the dump side: re-export with mysqldump --net-buffer-length=... to keep each extended insert smaller, or with --skip-extended-insert to write one row per statement. Both work. The second makes the file larger and the import slower. For wait_timeout, the better fix is often in the script rather than the server: reconnect or ping the connection before using it after long work, or open the connection only when you need it. Raising the global timeout keeps every idle connection on the server alive longer, which can use up max_connections on a busy host. For an OOM kill, neither setting helps. Reduce memory pressure during the import: stop or limit other heavy processes, check whether InnoDB buffer pool and per-connection buffers fit the RAM you actually have, or move to a plan with more memory. After the change, verify instead of assuming. Re-run the variable query and confirm the new value shows for a fresh connection. Re-run the import and check mysqladmin status afterward to confirm uptime kept counting through it. Look at the Aborted_clients counter in mysqladmin extended-status before and after: if it still climbs during the import, something is still closing connections. The short version: when you see "gone away", check uptime and the kernel log before you touch any config. If the server stayed up, measure the biggest statement in the dump and compare it with max_allowed_packet on both server and client. Treat wait_timeout as a suspect only when there is an actual idle gap. Each of these leaves evidence, and five minutes of reading it saves several rounds of guessing and re-importing.