Что означает “Got an error reading communication packets”
Сообщение Got an error reading communication packets появляется в логах MySQL/MariaDB, когда сервер ожидал данные от клиента по TCP-соединению, но чтение оборвалось: клиент закрыл соединение, сеть потеряла пакеты, промежуточный NAT/прокси «срезал» сессию по таймауту или сервер не дождался следующего фрагмента запроса/ответа.
Это не «ошибка SQL» в привычном смысле. Это симптом проблем на уровне транспорта (TCP) или параметров протокола (размеры пакетов и таймауты), поэтому лечится диагностикой «от сети к MySQL», а не наоборот.
Если ошибка всплывает на больших SELECT/INSERT/backup/репликации — в первую очередь проверяйте
max_allowed_packetиnet_read_timeout/net_write_timeout. Если она хаотичная и «плавает» по времени — чаще виноваты MTU/PMTUD, потери, NAT или proxy timeout.
Типовые сценарии, где встречается ошибка
Чаще всего вы попадёте в один из сценариев ниже.
- Большие запросы/строки (BLOB/TEXT), дампы, миграции, репликация: упираетесь в
max_allowed_packetили в таймауты чтения/записи. - «Долгий» запрос, а по пути стоит балансировщик/прокси/NAT, который рвёт idle-соединение: классический proxy timeout.
- Проблемы канала: packet loss, нестабильный VPN/туннель, «чёрная дыра» PMTUD (Path MTU Discovery), несовпадение MTU.
- Драйвер/пул соединений не синхронизирован с серверными таймаутами или агрессивно закрывает коннекты при рестартах приложений.
Если база крутится на отдельном сервере и соединений много, часто проще начинать диагностику на выделенной машине: на VDS удобнее изолировать сетевые эффекты, логи и метрики, чем на «общем» окружении.
Быстрая triage-проверка: что собрать за 10 минут
1) Смотрим, кто рвёт соединение и при каких условиях
На сервере БД полезно начать со статусов: они покажут, «отваливаются» ли клиенты и на каком этапе.
mysql -e "SHOW GLOBAL STATUS LIKE 'Aborted_%';"
mysql -e "SHOW GLOBAL STATUS LIKE 'Connections';"
mysql -e "SHOW GLOBAL STATUS LIKE 'Bytes_%';"
Подсказки по интерпретации:
Aborted_clientsрастёт — сессии часто обрываются уже после установления соединения.Aborted_connectsрастёт — проблемы на рукопожатии/аутентификации/доступе, либо «дропы» в сети на старте.
Дальше сразу снимите значения ключевых переменных:
mysql -e "SHOW GLOBAL VARIABLES WHERE Variable_name IN ('max_allowed_packet','net_read_timeout','net_write_timeout','wait_timeout','interactive_timeout');"
2) Проверяем, нет ли явных TCP-потерь/ретрансмиссий
Если приложение и MySQL на разных узлах, проверьте обе стороны. Начните с быстрых индикаторов TCP:
ss -ti dst :3306
netstat -s | egrep -i "retrans|timeout|listen|reset" | head
Если видите заметные ретрансмиссии, RTO, сбросы (RST) — сначала приводим в порядок сеть/туннель/виртуализацию. Настройками MySQL можно «смягчить» симптомы, но первопричину это не вылечит.

max_allowed_packet: почему его связывают с communication packets
max_allowed_packet ограничивает максимальный размер одного пакета в протоколе MySQL. На практике это проявляется так: большие INSERT (многострочные VALUES), BLOB/TEXT, длинные JSON, дампы с --hex-blob, репликация или восстановление формируют пакет, который превышает лимит на сервере или на клиенте.
Иногда при превышении вы увидите прямую ошибку «packet too large», но при нестабильной сети, прокси или дополнительных таймаутах цепочка выглядит иначе: отправка/чтение затягивается, возникают ретрансмиссии, и в логах «всплывает» именно Got an error reading communication packets.
Как проверить текущие лимиты
mysql -e "SHOW VARIABLES LIKE 'max_allowed_packet';"
Проверьте и клиентскую сторону: у CLI и утилит лимит может быть меньше, чем на сервере.
mysql --max_allowed_packet=256M -e "SELECT 1;"
mysqldump --max_allowed_packet=256M --single-transaction --quick dbname > dump.sql
Как безопасно увеличить max_allowed_packet
Если у вас реально большие payload, увеличение — нормальная практика. Но помните: слишком большой лимит повышает верхнюю границу потребления памяти на соединение в неблагоприятных сценариях.
Временно (до перезапуска, удобно для диагностики):
mysql -e "SET GLOBAL max_allowed_packet = 268435456;"
Постоянно (MySQL, Debian/Ubuntu-подобные пути):
cat >> /etc/mysql/mysql.conf.d/mysqld.cnf <<'EOF'
[mysqld]
max_allowed_packet = 256M
EOF
Постоянно (MariaDB, путь может отличаться):
cat >> /etc/mysql/mariadb.conf.d/50-server.cnf <<'EOF'
[mysqld]
max_allowed_packet = 256M
EOF
Применение:
systemctl restart mysql
Чтобы не упираться в ограничения «общего» окружения по ресурсам, MySQL под большие пакеты и миграции чаще комфортнее держать на отдельной VDS с предсказуемой сетью и диском.
Таймауты MySQL: net_read_timeout, net_write_timeout, wait_timeout
Когда запрос или ответ большой, данные идут частями. Если сеть «подвисла» или приложение долго не читает сокет, срабатывают таймауты — и вы получаете обрыв на чтении/записи, который затем выглядит как communication packets.
net_read_timeout
net_read_timeout — сколько секунд сервер ждёт следующую порцию данных от клиента. Имеет смысл увеличивать, если клиент отправляет большой запрос медленно (потери, VPN, перегруженное приложение, медленный аплоад).
mysql -e "SHOW VARIABLES LIKE 'net_read_timeout';"
mysql -e "SET GLOBAL net_read_timeout = 120;"
net_write_timeout
net_write_timeout — сколько секунд сервер ждёт, пока клиент прочитает отправляемые данные. Важен при больших SELECT/экспортах, когда клиент читает медленно или промежуточный прокси буферизует трафик.
mysql -e "SHOW VARIABLES LIKE 'net_write_timeout';"
mysql -e "SET GLOBAL net_write_timeout = 300;"
wait_timeout и interactive_timeout
wait_timeout — сколько сервер держит неактивное соединение, прежде чем закрыть. На фоне пулов соединений и прокси это критично: приложение может попытаться использовать «простаявший» коннект, который уже закрыт сервером или сетевым устройством.
mysql -e "SHOW VARIABLES LIKE 'wait_timeout';"
mysql -e "SHOW VARIABLES LIKE 'interactive_timeout';"
Чтобы не ловить «призрачные» обрывы, согласуйте между собой три слоя:
- idle/max lifetime в пуле соединений приложения;
wait_timeoutна сервере;- таймауты NAT/прокси/балансировщика на TCP.
Если вы используете репликацию/фейловер, полезно держать под рукой отдельный разбор сетевых «хвостов» при переключениях: GTID, semi-sync и фейловер MySQL: как избежать сюрпризов.
MTU issues и PMTUD: скрытая причина обрывов MySQL
MTU-проблемы особенно неприятны тем, что проявляются «не всегда»: мелкие пакеты ходят, а большие периодически «исчезают». Типовой кейс: между клиентом и сервером есть VPN, GRE, PPPoE, overlay-сеть контейнеров, либо где-то режется ICMP. В итоге PMTUD не работает, крупные TCP-сегменты попадают в «чёрную дыру», растут ретрансмиссии и задержки, а MySQL упирается в net_read_timeout/net_write_timeout и логирует ошибки про communication packets.
Как быстро проверить MTU до хоста (IPv4)
С клиента до сервера БД подберите максимальный размер без фрагментации:
ping -M do -s 1472 -c 3 DB_HOST
ping -M do -s 1464 -c 3 DB_HOST
1472 — это 1500 MTU минус 20 байт IPv4 header и 8 байт ICMP. Если не проходит, уменьшайте размер, пока не начнёт проходить стабильно. Дальше уже разбирайтесь, где именно в пути MTU меньше ожидаемого.
Что делать, если MTU реально меньше 1500
Дальнейшие действия зависят от инфраструктуры, но логика всегда одна: либо сделать MTU «честным» на интерфейсах, либо обеспечить корректную работу PMTUD.
- Выставьте корректный MTU на интерфейсах туннеля/оверлея и на хостах, чтобы избежать «чёрной дыры».
- Если ICMP фильтруется, разрешите сообщения, необходимые для PMTUD (иначе крупные пакеты будут теряться без явных ошибок).
- Как временная мера на границе — используйте TCP MSS clamping, чтобы большие сегменты не уходили в «провал».
Если трафик идёт через VPN, часто помогает правильный keepalive и параметры туннеля, чтобы NAT/маршрутизаторы не «забывали» состояние: WireGuard roaming и keepalive: как избежать отвалов.
Для прод-окружений, где вы реально заботитесь о целостности канала и шифровании на периметре, проверьте, что сертификаты выпускаются и обновляются без «ручного героизма»: SSL-сертификаты полезны, если нужно стандартизировать TLS для сервисов и админ-панелей.

Packet loss: как отличить потери от “просто таймаута”
Потери пакетов часто выглядят как «то работает, то нет»: часть запросов проходит, часть падает на чтении/записи. Особенно заметно на длительных выгрузках, миграциях и восстановлении из дампов.
Минимальный набор проверок:
mtr -rwz -c 200 DB_HOST
ss -ti dst DB_HOST:3306
В ss -ti смотрите на ретрансмиссии, RTO и общее поведение TCP. Если потери подтверждаются — чините сеть (линк, перегруз, виртуализацию, туннель, conntrack/NAT), а уже потом «полируйте» MySQL-таймауты.
Прокси и балансировщики: proxy timeout как причина обрывов
Если между приложением и MySQL стоит устройство или сервис, который может закрыть TCP-сессию (L4 LB, NAT gateway, sidecar proxy, SQL-proxy), появляется отдельный класс проблем: соединение рвётся «по правилам» промежуточного слоя, а MySQL пишет про communication packets.
Признаки обычно повторяемые:
- обрывы происходят примерно через фиксированный интервал простоя (60/300/900 секунд);
- короткие запросы всегда успешны, а длинные выгрузки падают ближе к одному и тому же времени;
- при прямом подключении (минуя прокси) проблема исчезает.
Решение — согласование таймаутов. Практическая цель: приложение должно либо обновлять соединение раньше, чем его закроет прокси/NAT, либо прокси должен держать MySQL-трафик достаточно долго. А wait_timeout на сервере не должен неожиданно «отстреливать» коннекты из пула.
Рекомендуемая последовательность действий (runbook)
Зафиксируйте контекст: какой запрос/операция выполнялась, примерный размер данных, через какие хосты/прокси идёт трафик.
Проверьте
max_allowed_packetна сервере и на клиенте. Если есть большие операции — увеличьте до разумного (часто 128M–512M) и повторите.Для миграций/бэкапов поднимите
net_read_timeoutиnet_write_timeout, особенно если канал не идеальный.Проверьте MTU/PMTUD через
ping -M do. При симптомах «чёрной дыры» чините MTU/ICMP/туннель, а не MySQL.Подтвердите или исключите потери:
mtr, TCP ретрансмиссии, счётчики интерфейса (ip -s link,ethtool -Sгде доступно).Сверьте таймауты всех промежуточных устройств с
wait_timeoutи политикой пула соединений приложения.
Набор «разумных» настроек для типичного прод-сервера
Универсальных значений нет, но как стартовая база для многих веб-проектов (API/админка/фоновые задачи) часто подходят такие диапазоны:
max_allowed_packet128M–256M, если бывают большие payload.net_read_timeout60–120, если бывают длинные отправки.net_write_timeout120–300, если бывают длинные выгрузки.wait_timeoutсогласовать с пулом соединений и прокси; часто это 60–600, но зависит от архитектуры.
Не «раздувайте» таймауты до бесконечности: это может скрыть реальные проблемы (например, потери) и привести к накоплению зависших соединений. Лучше сначала стабилизировать сеть и цепочку прокси, а затем выставить таймауты под ваши реальные операции (бэкапы, миграции, репликация, большие выборки).
Частые ошибки при исправлении
Увеличили только серверный
max_allowed_packet, забыв про клиентский (mysqldump/драйвер) — проблема осталась.Подняли
wait_timeout, но прокси/NAT всё равно режет соединение раньше — обрывы продолжаются.Игнорируют MTU issues и лечат таймаутами — становится «реже», но не исчезает, а миграции всё равно валятся.
Диагностируют только MySQL и не смотрят TCP ретрансмиссии — теряется главный сигнал о packet loss.
Чек-лист: что указать, если идёте в поддержку/к провайдеру
Чтобы проблему быстрее локализовали (особенно если подозрение на сеть), заранее соберите:
- время инцидента, IP/хосты клиента и сервера;
- значения
max_allowed_packet,net_read_timeout,net_write_timeout,wait_timeout(выводSHOW GLOBAL VARIABLES); - динамику
Aborted_clients/Aborted_connectsдо и после (выводSHOW GLOBAL STATUS); - результаты
mtr -rwz -c 200и тест MTU (ping -M do); - описание всех прокси/балансировщиков/NAT по пути и их таймаутов (если известны).
Итоги
Got an error reading communication packets — «зонтичный» симптом. В одних проектах он лечится просто: синхронизировали max_allowed_packet и аккуратно подняли net_read_timeout/net_write_timeout. В других — это индикатор сетевой проблемы: MTU/PMTUD, packet loss или немой разрыв из-за proxy timeout.
Оптимальная стратегия — идти по слоям: подтвердить или исключить MTU и потери, затем выровнять таймауты прокси/приложения/MySQL, и только после этого фиксировать значения переменных под ваши операции (бэкапы, миграции, репликация, большие выборки).


