Пример прерывания соединения MySQL, вызванного перегрузкой TCP-кеша

Как проанализировать возможность воздействия на другие факторы, помимо самой MySQL?

Автор: Гонг Танцзе, член группы администраторов баз данных ACOS, в основном отвечает за техническую поддержку MySQL и хорошо разбирается в MySQL, PG и отечественных базах данных.

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

Эта статья содержит около 1200 слов, и ее чтение займет 3 минуты.

фон

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

анализировать

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

  1. Клиент не закрыл соединение должным образом и не вызвал mysql_close()функцию.
  2. Если время простоя клиента превышает секунды, указанные в параметре wait_timeoutили interactive_timeout, сервер автоматически отключается.
  3. Размер пакета, отправленного или полученного клиентом, превышает max_allowed_packetзначение параметра, что приводит к прерыванию соединения.
  4. Клиент попытался получить доступ к базе данных, но не имел разрешения, либо был использован неправильный пароль, либо пакет подключения не содержал правильной информации.

Однако после расследования выяснилось, что ни одна из вышеперечисленных ситуаций не относится к текущей проблеме. Поскольку раньше задачи выполнялись нормально и программа не менялась, первую ситуацию можно исключить. Я проверил параметры таймаута MySQL wait_timeoutи interactive_timeoutобнаружил, что они оба равны 28800, что составляет 8 часов, что намного превышает время выполнения задачи, поэтому вторую ситуацию можно исключить. Я также проверил max_allowed_packetпараметры клиента и сервера и обнаружил, что они оба равны 64М и вряд ли превысят этот предел, поэтому третью ситуацию можно исключить. Мы также подтвердили, что права доступа к базе данных клиента, пароль, пакет подключения и другая информация верны, поэтому четвертую ситуацию можно исключить.

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

Чтобы определить проблему, мы попытались изменить некоторые соответствующие параметры ядра сервера следующим образом:

net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_time = 120
net.core.rmem_default = 2097152
net.core.wmem_default = 2097152
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_syn_backlog = 16384

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

Наконец, мы попытались проанализировать перехват пакетов. С помощью инструмента Wireshark мы обнаружили аномальное явление: сервер отправлял клиенту большое количество пакетов ACK. Как показано ниже:

Эти пакеты ACK являются пакетами подтверждения в протоколе TCP, указывающими, что сервер получил пакет данных клиента и запрашивает клиента продолжить отправку данных. Но почему сервер отправляет так много пакетов ACK? Мы предполагаем, что в сети может возникнуть аномалия, из-за которой клиент не получает пакет ACK, возвращенный сервером, поэтому сервер будет повторно отправлять пакеты ACK до тех пор, пока не истечет время ожидания или не получит ответ от клиента. Однако после расследования, проведенного персоналом сети, явных проблем обнаружено не было.

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

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

[TCP Window Full] — это окно-предупреждение, отправляемое отправителем получателю и указывающее, что достигнут предел получателя данных.

[TCP ZeroWindow] — это окно-предупреждение, отправленное принимающей стороной отправляющей стороне, сообщающее отправителю, что окно приема принимающей стороны заполнено и временно прекращает отправку.

Основываясь на приведенной выше информации, мы предполагаем, что причина проблемы заключается в следующем: поскольку данные, которые MySQL должен отправить, слишком велики, TCP-кеш клиента заполнен, поэтому ему необходимо дождаться, пока клиент переварит данные в TCP. кэш, прежде чем он сможет продолжать получать данные. Однако в течение этого периода MySQL будет продолжать запрашивать клиента продолжить отправку данных. Если клиент не отвечает в течение определенного периода времени (по умолчанию — 60 секунд), MySQL посчитает, что время отправки данных истекло, и прервет соединение.

Чтобы проверить это предположение, я проверил медленный журнал MySQL и обнаружил множество записей Last_errno: 1161 .

Эти записи указывают на то, что MySQL обнаружил ошибку тайм-аута при отправке данных, и количество таких случаев очень близко к количеству неудачных задач приложения. Согласно официальному сайту MySQL, смысл этой ошибки следующий:

Номер ошибки: 1161; Символ: ER_NET_WRITE_INTERRUPTED; SQLSTATE: 08S01

Сообщение: Получен тайм-аут записи пакетов связи.

Видно, что это означает, что сетевая запись прерывается, и на уровне MySQL есть параметр для управления этим, поэтому попробуйте изменить параметр net_write_timeout на 600, и пакетная задача запустится нормально.

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

в заключение

Благодаря приведенному выше анализу и попыткам мы пришли к следующим выводам:

  • В информации захвата пакетов содержится много информации ACK, поскольку кэш клиента заполнен и не может вовремя отправить обратную связь серверу, поэтому сервер будет повторно отправлять информацию ACK до тех пор, пока не пройдет более 60 секунд ( net_write_timeoutзначение по умолчанию — 60), вызывая MySQL, чтобы прервать соединение.
  • В медленном журнале много записей Last_errno:1161, потому что SQL действительно выполнялся в MySQL, но при отправке данных клиенту объем данных превышает TCP-кеш клиента, и тогда клиентское приложение не обработало данные в кэше в течение 60 секунд, что приводит к тайм-ауту MySQL при отправке данных клиенту.
  • Настройка net_write_timeoutпараметров на уровне MySQL может только смягчить это явление. Основная причина заключается в том, что объем данных, получаемых одним SQL, слишком велик и превышает размер кэша клиента. Приложение не может обработать данные в кэше за короткое время. что приводит к тайм-ауту последующей отправки данных.

Предложения по оптимизации

  • Данные обрабатываются пакетами на бизнес-уровне, чтобы избежать получения большого объема данных с сервера одним SQL-запросом, что приводит к недостаточности кэша TCP на стороне клиента.
  • Увеличение параметров MySQL net_write_timeoutили увеличение TCP-кеша клиента может облегчить эту ситуацию, но не может полностью решить проблему, поскольку слишком большой объем данных все равно будет влиять на производительность и стабильность.
  • Оптимизируйте операторы SQL, чтобы уменьшить ненужные возвраты данных, например использование LIMIT, WHERE и других условий или использование агрегатных функций, функций группировки и т. д., чтобы уменьшить объем данных и повысить эффективность запросов.

Дополнительные технические статьи можно найти на странице https://opensource.actionsky.com/ .

О SQLE

SQLE — это комплексная платформа управления качеством SQL, которая охватывает аудит и управление SQL от среды разработки до производственной среды. Он поддерживает основные базы данных с открытым исходным кодом, коммерческие и отечественные базы данных, обеспечивает возможности автоматизации процессов разработки, эксплуатации и обслуживания, повышает онлайн-эффективность и качество данных.

SQLE получить

тип адрес
Репозиторий https://github.com/actiontech/sqle
документ https://actiontech.github.io/sqle-docs/
выпускать новости https://github.com/actiontech/sqle/releases
Документация по разработке плагина аудита данных https://actiontech.github.io/sqle-docs/docs/dev-manual/plugins/howtouse
Линус взял дело в свои руки, чтобы не дать разработчикам ядра заменять табуляции пробелами. Его отец — один из немногих руководителей, умеющих писать код, его второй сын — директор отдела технологий с открытым исходным кодом, а младший сын — ядро. Соавтор открытого исходного кода Huawei: потребовался 1 год для преобразования 5000 часто используемых мобильных приложений. Комплексный переход на Hongmeng Java — язык, наиболее подверженный сторонним уязвимостям. Ван Чэнлу, отец Hongmeng: Hongmeng с открытым исходным кодом — единственная архитектурная инновация. в области базового программного обеспечения в Китае Ма Хуатенг и Чжоу Хунъи пожимают друг другу руки, чтобы «избавиться от обид». Бывший разработчик Microsoft: производительность Windows 11 «смехотворно плоха» « Хотя то, что Laoxiangji является открытым исходным кодом, - это не код, а причины этого. Meta Llama 3 официально выпущена. Google объявляет о масштабной реструктуризации .
{{o.name}}
{{m.name}}

рекомендация

отmy.oschina.net/actiontechoss/blog/11054532
рекомендация