Самый дешевый способ определить, живо ли соединение MySQL - PullRequest
12 голосов
/ 30 марта 2010

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

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

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

Пояснение: Меня не беспокоит проверка того, работает ли сервер MySQL или его конфигурация базы данных достаточна для ответа на запросы. Если эти вещи не работают, то последующий SQL, который выполняет служба, получит и обработает соответствующую ошибку. Меня действительно беспокоит, если TCP-соединение открыто… поскольку, если сервер закрыл его, SQL-запрос веб-службы получит ошибку, которая означает «просто переподключитесь и попробуйте снова», и это было бы неудобно делать один раз в Гадость сервисного кода.

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

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

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

Ответы [ 3 ]

13 голосов
/ 30 марта 2010

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

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

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

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

Поэтому я бы порекомендовал:

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

UPDATE

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

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

ОБНОВЛЕНИЕ 2

Относительно сообщения Джошуа , вот следы захвата пакета для различных сценариев:

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 байтов вместо 9 байтов DO 1;, количество циклических возвратов (и, следовательно, задержка, вызванная сетью) точно такое же. Единственная дополнительная плата, которую вы платите DO 1, а не mysql_ping, - это анализ DO 1, что тривиально.

6 голосов
/ 31 марта 2010

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

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

select 1

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

/* ping */ select 1

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

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

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

1 голос
/ 30 марта 2010

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

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

...