Просмотров: 5821

MySQL: SQL или NoSQL - вот в чем вопрос. Команды HandlerSocket


Ознакомившись с основами HS в предыдущем посте, продолжим погружение в устройство этого NoSQL-протокола.

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

MySQL plugin плагин NoSQL HandlerSocket Memcached хранилище highload Drizzle NewSQL схема производительность замеры тест тесты скорость график таблица

Итак, HandlerSocket — это простой протокол типа «запрос-ответ». Что касается ответа, то дополнительно нужно учесть, что он может быть пакетным (что-то вроде multi_get в memcache). Это значит, что сервер может принимать запросы в конвейерном режиме (каждый запрос — 1 строка) накапливая их какой-то целесообразный промежуток времени, а затем выстреливая единым ответным пакетом на все предшествовавшие запросы данного клиента (одной общей строкой). Все параметры в этом протоколе разделяются между собой символом TAB .

Основные команды HandlerSocket

Хотя набор команд у HS невелик, для краткости приведем в качестве примера синтаксис лишь его трех главных команд.

Запрос на открытия индекса OPEN_INDEX

P <indexid> <dbname> <tablename> <indexname> <columns>

  • Здесь indexid — это уникальный номер индекса (открытого канала) в десятичном виде. Для закрытия канала нужно просто повторно выполнить «open_index » для требуемого индекса, ранее открытого этой же командой. Что, кстати, лишний раз говорит о необходимости внимательного выбора и учета используемых значений indexid , чтобы избежать ненужных ошибок в программировании;
  • dbname, tablename и indexname — строки, обозначающие соответственно имя БД, имя таблицы и имя индекса. Для открытия индекса на первичный ключ, нужно применять PRIMARY к indexname ;
  • Параметр columns — список колонок через запятую. Если однажды запрос «open_index » был успешно выполнен, плагин будет держать этот канал (идентифицируемый целым числом indexid ) открытым, пока он не будет закрыт или не истечет время установленного таймаута.

Допускается параллельно открывать любое количество каналов с аналогичным (или любым другим) сочетанием dbname, tablename и indexname , единственно, рекомендуется при этом выбирать наименьшее значение indexid из доступных.

Если индекс был открыт успешно, HandlerSocket возвращает строку — «0 1».

Обновление/удаление данных FIND_MODIFY

<indexid> <op> <vlen> <v1> … <vn> <limit> <offset> <mop> <m1> … <mk>

  • indexid — номер индекса (канала), по которому необходимо производить поиск. Первоначально он должен быть выделен через комманду open_index (см. выше);
  • op — это операция сравнения, которая будет производиться при поиске. Доступны следующие стандартные операции сравнения: ‘=’, ‘>’, ‘>=’, ‘<’, ‘<=’. Отдельно подчеркну, что при выборке по символьным индексам необходимо обязательно учитывать кодировку, так как это может приводить к некоторым неожиданностям;
  • vlen — длина строки параметров (v1 ... vn — смотрите описание ниже). Их количество должно быть меньше или равно количеству колонок в индексе, определённых при операции open_index ;
  • v1... vn — определяет непосредственно сами значения колонок, которые и нужно искать;
  • limit, offset — числа. По своему смыслу они полностью аналогичны параметрам LIMIT и OFFSET в стандартном SQL-запросе. Это необязательные параметры (по умолчанию используются значения 1 и 0);
  • mop — это код операции, возможно значение ‘U’ (при обновлении) или ‘D’ (при удалении);
  • m1... mk — перечисление значений для колонок, которые надо установить (если код mop равен ‘D’, эти параметры игнорируются).

Если запрос ‘find_modify ’ выполнен успешно, HandlerSocket возвратит строку такого вида: 0 1 numfound , где numfound — это количество строк, удовлетворяющих запросу.

Вставка данных INSERT

<indexid> ‘+’ <vlen> <v1> … <vn>

  • indexid — номер индекса (канала), по которому необходимо производить поиск;
  • vlen — определяет длину строки параметров v1 ... vn ;
  • v1...vn — определяет значения колонок, которые нужно вставить.

Если INSERT был выполнен успешно, возвращается уже стандартная ответ-строка — «0 1 ».

Общий формат ответов

Первое число в ответе является значением errorcode  — и если оно отлично от нуля — операция завершилась с ошибкой, а само значение errorcode в этом случае будет обозначать код ошибки. Второе число — numcolumns — всегда возвращает количество колонок в результирующей выборке. В некоторых случаях возвращаются также и значения выборки (если это предполагается операцией) — r1 ... rn , — при этом их количество в этом случае, очевидно, должно совпадать со значением numcolumns . Таким образом, формат любого ответа в рамках HandlerSocket в общем случае будет иметь вид:

<errorcode> <numcolumns> <r1> ... <rn>

Все ответные данные, также как и параметры самих запросов, разделяются символом TAB (\t) , каждая строка запроса (ответа) оканчивается BK (\n) .

В качестве примера: типичный ответ на успешное открытие (закрытие) индекса будет иметь вид «0 1 ». Этот же ответ будет возвращаться чаще всего и как подтверждение успешного завершения операций и у других вызовов. Описание всех 6 команд HandlerSocket и тонкостей их применения можно найти в официальной документации проекта.

Пробуем HandlerSocket в деле

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

CREАTE TАBLE `test`.`test` (
`keyid` varchar(30),
`value` varchar(30),
PRIMARY KЕY (`keyid`)
)

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

telnet 192.168.1.10 9999
Trying 192.168.1.10...
Connected to 192.168.1.10.
Escape character is ’^]’.
P 0 test test PRIMARY keyid,value
0 1
0 = 1 5555 1 0 D
0 1 1
0 + 2 1111 2222 3333
0 1

В качестве первой помощи, давайте я прокомментирую этот «поисковый ассемблер» построчно, чтобы лучше уловить устройство протокола HandlerSocket:

//Инициализируем канал, подключились к модифицирующему потоку (порт 9999) 
P 0 test test PRIMARY keyid,value
//0 1 — открытие канала с данными параметрами прошло успешно
0 1
// Используем вызов FIND_MODIFY для канала 0
0 = 1 5555 1 0 D
// здесь по-порядку идут: номер канала(0), тип операции (=), кол-во ключей 
(1), значение, которое ищем (в нашем случае — 5555), код операции — D (то 
есть удаление всего найденного).
0 1 1
// запрос успешно выполнен (0 1), количество обработанных строк — 1
0 + 2 1111 2222 
// для открытого канала (0) делаем запрос на вставку данных (vlen=2, значения колонок для вставки: 1111, 2222)
0 2
// запрос успешно выполнен (формат любого ответа — <errorcode> <numcolumns>)

В качестве примеров демонстрации возникновения ошибок, приведу пример попытки модификации канала при открытии его в режиме чтения (через порт 9998), а также открытия несуществующего индекса:

telnet 192.168.1.10 9998
Trying 192.168.1.10...
Connected 192.168.1.10.
Escape character is ’^]’.
P 0 test test PRIMARY keyid,value
0 1
0 = 1 77777 0 0 D
2 1 readonly
P 1 test notest PRIMARY nokey,noval
3 0

Кроме этого приведу пример доступа к запароленному потоку, сначала приводящий к ошибке доступа (3 1 unauth ), а затем я показываю пример успешной авторизации (недокументированная команда A, пароль в данном случае — samag ).

Здесь сервер возвращает статус «0 1», что, согласно документации, эквивалентно сообщению об успешном завершении операции open_index (в нашем контексте это значит скорее «авторизация прошла успешно»):

P 0 test test PRIMARY keyid,value
3 1 unauth
0 = 1 1
3 1 unauth
A 1 samag
0 1

~

Читать этот материал дальше. Оглавление этой серии статей — здесь.

Игорь Савчук ©  Системный Администратор, 2011
twitter.com facebook.com vkontakte.ru odnoklassniki.ru mail.ru ya.ru pikabu.ru blogger.com liveinternet.ru livejournal.ru google.com bobrdobr.ru yandex.ru del.icio.us

Подписка на обновления блога → через RSS, на e-mail, через Twitter
Теги: , , , , , , , ,
Эта запись опубликована: Вторник, 20 марта 2012 в рубрике Unix'овоеПрограммирование.

Оставьте комментарий!

Не регистрировать/аноним

Используйте нормальные имена. Ваш комментарий будет опубликован после проверки.

Зарегистрировать/комментатор

Для регистрации укажите свой действующий email и пароль. Связка email-пароль позволяет вам комментировать и редактировать данные в вашем персональном аккаунте, такие как адрес сайта, ник и т.п. (Письмо с активацией придет в ящик, указанный при регистрации)

(обязательно)


⇑ Наверх
⇓ Вниз