MySQL: Too many connections — как найти причину и исправить

Пошагово проверяем причину ошибки MySQL Too many connections и решаем проблему без массового завершения важных соединений.

Ошибка:

ERROR 1040 (HY000): Too many connections

означает, что MySQL больше не может принять обычное новое подключение: доступные соединения уже заняты другими клиентами. В MySQL количество одновременных подключений ограничивает параметр max_connections.

Но просто увеличить этот параметр — не всегда правильное решение.

Если приложение начало создавать слишком много подключений, перестало освобождать их или на сервере накопились долгие соединения, увеличение лимита только отложит повторение ошибки.

Сначала нужно понять, кто занял подключения и почему их стало так много.

Сначала проверьте текущий лимит

↑ К оглавлению

Подключитесь к MySQL с административной учётной записью и выполните:

SHOW VARIABLES LIKE 'max_connections';

Затем посмотрите, сколько подключений открыто прямо сейчас:

SHOW GLOBAL STATUS LIKE 'Threads_connected';

Threads_connected показывает количество текущих открытых соединений.

Полезно также посмотреть максимальное количество одновременно использовавшихся подключений с момента запуска сервера:

SHOW GLOBAL STATUS LIKE 'Max_used_connections';

Если Max_used_connections регулярно приближается к max_connections, проблема действительно связана с исчерпанием доступных соединений. MySQL отдельно ведёт этот показатель как максимальное число одновременно использовавшихся подключений.

Проверьте, действительно ли MySQL упирался в лимит

↑ К оглавлению

MySQL считает подключения, которые были отклонены именно из-за достижения max_connections.

Проверьте:

SHOW GLOBAL STATUS LIKE 'Connection_errors_max_connections';

Если значение увеличивается, MySQL действительно отклоняет новые подключения из-за заполненного лимита.

Это полезнее, чем делать вывод только по жалобе приложения: ошибки соединения могут возникать и по другим причинам.

Посмотрите, кто держит подключения

↑ К оглавлению

Следующий шаг:

SHOW FULL PROCESSLIST;

Список процессов показывает текущие соединения и то, чем они занимаются.

Обратите внимание на:

  • User — под какой учётной записью установлено соединение;
  • Host — откуда пришло подключение;
  • db — с какой базой оно работает;
  • Command;
  • Time;
  • State;
  • Info.

MySQL позволяет использовать process list именно для диагностики работающих соединений. Для просмотра чужих потоков нужны соответствующие права.

Задача здесь не в том, чтобы сразу удалять соединения, а в том, чтобы увидеть закономерность.

Например:

  • сотни соединений от одного приложения;
  • большое количество долго висящих Sleep;
  • много одновременно выполняющихся запросов;
  • соединения с одного конкретного сервера;
  • одна учётная запись занимает почти весь лимит.

Если много соединений в состоянии Sleep

↑ К оглавлению

Sleep означает, что клиент подключён к MySQL, но сейчас не выполняет запрос.

Само по себе это нормально. Например, приложение может использовать пул соединений и держать несколько подключений открытыми для повторного использования.

Проблема появляется, если таких соединений становится значительно больше, чем должно быть.

Тогда нужно проверить приложение:

  • ограничен ли размер пула соединений;
  • возвращает ли приложение соединения обратно в пул;
  • закрываются ли соединения после работы;
  • не создаётся ли новое подключение при каждом запросе без повторного использования;
  • не запущено ли слишком много одинаковых экземпляров приложения.

Просто удалить все Sleep-соединения — временное решение. Если приложение продолжает создавать их тем же способом, лимит заполнится снова.

Проверьте wait_timeout

↑ К оглавлению

MySQL может автоматически закрывать неактивные неинтерактивные подключения.

За это отвечает:

SHOW VARIABLES LIKE 'wait_timeout';

wait_timeout задаёт время, в течение которого сервер ждёт активности на неинтерактивном соединении перед его закрытием. В MySQL 8.4 этот параметр динамический и задаётся в секундах.

Но резко уменьшать wait_timeout наугад не стоит.

Если приложение рассчитывает на долгоживущие соединения и неправильно обрабатывает их закрытие сервером, вместо Too many connections можно получить уже другие ошибки.

Сначала правильнее проверить работу самого приложения и его connection pool.

Если много активных соединений

↑ К оглавлению

Посмотрите также:

SHOW GLOBAL STATUS LIKE 'Threads_running';

Threads_running показывает число потоков, которые сейчас не находятся в состоянии сна.

Если Threads_connected велик, но активно работает только небольшая часть соединений, внимание стоит обратить на idle-подключения и пул.

Если одновременно велик и Threads_running, причина может быть другой:

  • резкий рост нагрузки;
  • большое число параллельных запросов;
  • медленные запросы;
  • блокировки;
  • приложение запускает слишком много операций одновременно.

В такой ситуации увеличение max_connections может даже ухудшить положение: сервер получит ещё больше параллельной работы, хотя первоначальная проблема останется.

Не путайте с лимитом отдельного пользователя

↑ К оглавлению

У MySQL есть ещё один механизм — ограничение числа соединений для конкретной учётной записи.

Это может быть глобальный:

max_user_connections

или индивидуальный MAX_USER_CONNECTIONS для пользователя.

Если достигнут именно этот предел, MySQL может вернуть другую ошибку:

User ... already has more than 'max_user_connections' active connections

В справочнике MySQL это отдельная ошибка 1203 / ER_TOO_MANY_USER_CONNECTIONS.

Поэтому перед изменением max_connections нужно посмотреть точный текст ошибки.

Что делать, если к MySQL уже невозможно подключиться

↑ К оглавлению

MySQL предусматривает дополнительное административное подключение сверх обычного max_connections.

Оно предназначено для учётной записи с привилегией CONNECTION_ADMIN — в старых версиях для этой цели использовалась привилегия SUPER.

Это позволяет администратору подключиться к переполненному серверу и выполнить диагностику через process list.

Поэтому административную учётную запись не стоит использовать в обычном приложении.

Она должна оставаться именно инструментом администратора.

Можно ли просто увеличить max_connections

↑ К оглавлению

Можно, и MySQL позволяет изменять max_connections во время работы сервера.

Но сначала ответьте на вопрос:

серверу действительно нужно больше нормальных одновременных подключений или текущие подключения расходуются неправильно?

Увеличение оправдано, например, когда:

  • нагрузка выросла естественным образом;
  • количество приложений действительно увеличилось;
  • connection pool настроен правильно;
  • соединения освобождаются нормально;
  • сервер имеет достаточные ресурсы;
  • текущий лимит объективно слишком мал для нагрузки.

Если же одно приложение бесконтрольно создаёт соединения, увеличение лимита лечит только симптом.

Временное и постоянное изменение — не одно и то же

↑ К оглавлению

Изменение глобального значения во время работы влияет на текущий экземпляр MySQL.

Например, администратор может изменить динамический параметр через SET GLOBAL.

Но такое изменение само по себе не обязательно переживёт перезапуск сервера.

В современных версиях MySQL существует SET PERSIST: он меняет значение и сохраняет его для последующих запусков сервера.

Например:

SET PERSIST max_connections = 250;

250 здесь только пример, а не рекомендуемое значение для любого сервера.

Нужный лимит выбирают после проверки реальной нагрузки и ресурсов.

Если MySQL управляется хостингом или облачной платформой, постоянное значение иногда настраивается через панель или параметры управляемого сервиса, а не непосредственно через конфигурацию MySQL.

Не убивайте соединения массово без проверки

↑ К оглавлению

При аварии возникает соблазн посмотреть process list и отключить всё лишнее.

Это может быстро освободить подключения, но сначала нужно определить, что именно вы отключаете.

Соединение может:

  • выполнять запрос;
  • держать транзакцию;
  • удерживать блокировки;
  • выполнять важную операцию приложения.

Принудительное завершение работающего соединения способно привести к откату незавершённой транзакции, а откат большой транзакции сам по себе может занять время.

Поэтому сначала диагностируйте соединения, а уже потом завершайте конкретные ненужные процессы.

Что чаще всего нужно исправлять в приложении

↑ К оглавлению

Если проблема возвращается, смотреть нужно не только MySQL.

Проверьте код или настройки приложения:

  1. сколько подключений разрешено каждому экземпляру приложения;
  2. сколько экземпляров приложения одновременно запущено;
  3. возвращаются ли соединения в pool после запроса;
  4. есть ли верхний предел размера pool;
  5. что происходит при ошибке — освобождается ли соединение;
  6. не создаёт ли background worker отдельные подключения бесконтрольно;
  7. не открываются ли новые соединения при каждом повторе запроса.

Например, если запущено десять процессов приложения и каждому разрешено до 30 соединений, потенциально они могут запросить уже 300 подключений.

Поэтому размер одного пула нельзя выбирать отдельно от количества процессов.

После исправления проверьте результат

↑ К оглавлению

После изменения настроек не ограничивайтесь тем, что сайт снова открылся.

Проверьте:

SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Threads_running';
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
SHOW GLOBAL STATUS LIKE 'Connection_errors_max_connections';

Затем наблюдайте за ними во время обычной и пиковой нагрузки.

Если количество соединений снова постепенно подползает к лимиту, проблема не устранена.

Короткий порядок диагностики

↑ К оглавлению

При MySQL Too many connections я бы проверял так:

  1. сохранить точный текст ошибки;
  2. посмотреть max_connections;
  3. проверить Threads_connected;
  4. проверить Max_used_connections;
  5. проверить Connection_errors_max_connections;
  6. открыть SHOW FULL PROCESSLIST;
  7. определить, какое приложение или пользователь занимает соединения;
  8. разделить активные и простаивающие подключения;
  9. проверить connection pool и освобождение соединений в приложении;
  10. проверить max_user_connections, если ошибка относится к одному пользователю;
  11. только после этого решать, действительно ли нужно увеличивать max_connections;
  12. после исправления повторно проверить нагрузку.

Так можно исправить причину, а не просто поднять предел до следующего сбоя.

Чего не стоит делать

↑ К оглавлению

При ошибке Too many connections не стоит сразу:

  • выставлять очень большое значение max_connections;
  • перезапускать MySQL каждый раз, когда соединения заканчиваются;
  • массово завершать все процессы;
  • уменьшать wait_timeout до нескольких секунд без проверки приложения;
  • выдавать административные права обычной учётной записи сайта;
  • считать каждый Sleep зависшим соединением;
  • менять сразу несколько параметров и потом пытаться понять, что помогло.

Сначала измерьте текущее состояние, найдите источник подключений и исправьте его.

Частые вопросы

Что означает MySQL Too many connections?

Это означает, что MySQL исчерпал доступные обычные клиентские подключения. Их общее количество ограничивает max_connections. Сначала нужно проверить текущие и максимальные соединения и определить, кто занимает доступные места.

Нужно ли увеличивать max_connections?

Не обязательно. Если лимит соответствует серверу, но приложение создаёт слишком много соединений или не возвращает их в пул, увеличение лишь временно скрывает проблему. Повышать лимит имеет смысл после диагностики нагрузки.

Почему много соединений MySQL находится в Sleep?

Это подключённые клиенты, которые сейчас не выполняют запрос. Для connection pool это может быть нормально. Проблема возникает, если idle-соединений становится больше ожидаемого и они заполняют весь доступный лимит.

Как подключиться к MySQL, если лимит соединений уже исчерпан?

MySQL предусматривает дополнительное административное подключение для учётной записи с привилегией CONNECTION_ADMIN. Оно позволяет администратору подключиться даже при заполненном обычном лимите и посмотреть процессы.

↑ К оглавлению

Нужна помощь с MySQL?

Поможем найти причину переполнения подключений, проверить сервер и приложение и восстановить стабильную работу базы данных.

↑ К оглавлению