Подтвердить что ты не робот

Самый дешевый способ определить, жив ли соединение MySQL

У меня есть пул соединений MySQL для веб-службы данных. Когда он начинает обслуживать запрос, для его использования требуется соединение из пула. Проблема заключается в том, что если была значительная пауза, так как это конкретное соединение было использовано, сервер, возможно, приурочил его и закрыл его конец. Я хотел бы иметь возможность обнаружить это в коде управления пулами.

Хитрость такова: среда, в которой я кодирую, дает мне только очень абстрактный API в соединение. Я могу в основном выполнять только SQL-запросы. У меня нет доступа к фактическому сокету или прямому доступу к API-интерфейсу клиента MySQL.

Итак, вопрос: Что такое самый дешевый оператор MySQL, который я могу выполнить в соединении, чтобы определить, работает ли он. Например, SELECT 1; должен работать, но мне интересно, есть ли что-то еще дешевле? Возможно, что-то, что даже не проходит через провод, но обрабатывается в клиентской библиотеке MySQL и эффективно отвечает на один и тот же вопрос?

Уточнение: Меня не интересует проверка работы сервера MySQL или настройка базы данных для ответа на запросы. Если эти вещи не работают, то последующий SQL, который выполняет служба, получит и обработает соответствующую ошибку. Я действительно обеспокоен только тем, что TCP-соединение открыто... поскольку, если сервер закрыл его, тогда SQL-служба SQL получит ошибку, которая означает "просто повторно подключиться и повторить попытку", и это было бы неудобно делать, гадость служебного кода.

Закрытие: Хвост /* ping */ - это именно то, что я искал, но, увы, доступно только через JDBC. Прочитав документы для этого взлома, ясно, что он был помещен туда по той же причине, что и я. Для любопытных я работаю в Haskel, используя HDBC и HDBC-mysql. Я попрошу автора HDBC-mysql добавить способ вызова mysql_ping() либо напрямую, либо с помощью аналогичного взлома.

Влад DO 1 тоже был тем, чем я был, и, поскольку другой хак недоступен вне JDBC, я его буду использовать.

Спасибо за отличное обсуждение, особенно @Vlad!

4b9b3361

Ответ 1

Вы не узнаете реальное состояние соединения, не пройдя провод, а SELECT 1 - достаточно хороший кандидат (возможно, вы можете придумать более короткую команду, которая занимает меньше времени разобрать, но по сравнению с задержкой в ​​сети или даже обратной петлей эти сбережения будут незначительными.)

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

Вероятно, вам просто нужно, чтобы диспетчер пула соединений применял свою собственную политику keep-alive (timeout), чтобы не быть отключенным сервером (если не считать более серьезной проблемы с подключением, которая может повлиять на вас так или иначе, и менеджер вашего пула соединений не смог бы помочь в любом случае), а также , чтобы не запускать базу данных (думаю, дескрипторы файлов и использование памяти).

Поэтому сомнительно, на мой взгляд, какое значение тестирует условие подключения, прежде чем проверять соединение из пула. Возможно, стоит проверить статус подключения до того, как соединение будет проверено обратно в пул, но это можно сделать неявно, просто отметив соединение как грязное, когда возникает сложная ошибка SQL (или эквивалентное исключение) если только API, который вы используете, уже предоставляет вам вызов is-bad.)

Поэтому я рекомендую:

  • реализация политики поддержания работоспособности на стороне клиента
  • не выполняет никаких проверок при проверке соединений из пула
  • выполнение грязных проверок перед возвратом соединения в пул
  • пусть код приложения относится к другим (не-таймаутам) исключительным условиям соединения

UPDATE

Из ваших комментариев будет видно, что вы действительно действительно хотите связать соединение (я предполагаю, что это связано с тем, что вы не имеете полного контроля или знания характеристик тайм-аута на сервере MySQL или промежуточного сетевого оборудования, такого как прокси-серверы и др.)

В этом случае вы можете использовать DO 1 в качестве альтернативы SELECT 1; он немного быстрее - короче разобрать, и он не возвращает фактические данные (хотя вы получите TCP ack s, поэтому вы все равно сделаете кругооборот, подтверждающий, что соединение все еще установлено.)

ОБНОВЛЕНИЕ 2

Что касается Joshua post, здесь трассировки захвата пакетов для различных сценариев:

SELECT 1;
13:51:01.463112 IP client.45893 > server.mysql: P 2270604498:2270604511(13) ack 2531191393 win 1460 <nop,nop,timestamp 2983462950 59680547>
13:51:01.463682 IP server.mysql > client.45893: P 1:57(56) ack 13 win 65306 <nop,nop,timestamp 59680938 2983462950>
13:51:01.463698 IP client.45893 > server.mysql: . ack 57 win 1460 <nop,nop,timestamp 2983462951 59680938>

DO 1;
13:51:27.415520 IP client.45893 > server.mysql: P 13:22(9) ack 57 win 1460 <nop,nop,timestamp 2983488906 59680938>
13:51:27.415931 IP server.mysql > client.45893: P 57:68(11) ack 22 win 65297 <nop,nop,timestamp 59681197 2983488906>
13:51:27.415948 IP client.45893 > server.mysql: . ack 68 win 1460 <nop,nop,timestamp 2983488907 59681197>

mysql_ping
14:54:05.545860 IP client.46156 > server.mysql: P 69:74(5) ack 78 win 1460 <nop,nop,timestamp 2987247459 59718745>
14:54:05.546076 IP server.mysql > client.46156: P 78:89(11) ack 74 win 65462 <nop,nop,timestamp 59718776 2987247459>
14:54:05.546092 IP client.46156 > server.mysql: . ack 89 win 1460 <nop,nop,timestamp 2987247459 59718776>

Как вы можете видеть, за исключением того факта, что пакет mysql_ping равен 5 байтам вместо DO 1; 9 байтов, число обращений в оба конца (и, следовательно, задержка по сети) является точно таким же. Единственная дополнительная стоимость, которую вы платите с DO 1, а не mysql_ping, - это разбор DO 1, который тривиален.

Ответ 2

Я не уверен, какой API вы используете в настоящее время (или на каком языке), но для Java существует специальный трюк, который может сделать драйвер JDBC.

Стандартный тестовый запрос:

select 1

как вы указали. Если вы измените его на:

/* ping */ select 1

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

Я узнал об этом в эпизоде ​​Sun Deep Dive под названием Советы MySQL для разработчиков Java с Марком Мэтьюсом.

Даже если вы не используете Java, возможно, этот же трюк был реализован в других драйверах mysql? Я предполагаю, что серверу необходимо будет знать об этом специальном пакете, чтобы он мог отправить ответ...

Ответ 3

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

Если вы просто хотите узнать, слушает ли служба, вы должны иметь возможность выполнить вызов на сетевом уровне, чтобы узнать, прослушивает ли порт (не знаю, что по умолчанию) на целевом IP-адресе. Если вы хотите, чтобы механизм MySQL реагировал, я думаю, что ваша идея SELECT 1 хороша - на самом деле она не извлекает данные из базы данных, а подтверждает, что двигатель развернут и отвечает.