Комментарии 6
Great breakdown of prepared statements in Manticore Search. I especially like how you showed the difference between raw SQL and the parameterized version. I’m curious: how does the performance of prepared statements in Manticore compare to plain queries under heavy read/write load, and are there any best practices for batching parameterized queries?
We didn't benchmark it, but it's an interesting question. We'd appreciate it if you could do that and share your findings. What exactly do you mean by "batching"?
Thanks for the clarification, that makes sense. By “batching” I meant sending many parameter sets for the same prepared statement in one go (for example, inserting/updating a large number of rows in a single round‑trip instead of one by one) to see how much overhead the prepare/bind/execute cycle adds compared to plain SQL. I’ll try to set up a small benchmark with Manticore Load or a custom script to compare single‑row vs multi‑row/batched inserts and SELECTs using prepared statements vs normal queries, and will share the results once I have something meaningful.
Manticore Search поддерживает prepared statements через стандартный протокол MySQL, и это даёт вам удобный инструмент для создания безопасных поисковых приложений.
"Prepared statements через стандартный протокол MySQL", на который вы ссылаетесь, предполагает, что на сервер MySQL передаются запросы:
PREPARE stmt FROM {строка с текстом запроса с плейсхолдерами,
или определённая пользователем переменная с текстом запроса};
EXECUTE stmt USING ( {набор параметров № 1} );
EXECUTE stmt USING ( {набор параметров № 2} );
...
DROP PREPARE stmt;Однако всё, написанное далее, говорит о том, что Manticore Search ИГНОРИРУЕТ стандартные prepared statements в MySQL и выполняет все операции САМОСТОЯТЕЛЬНО. Экранирует переданные значения, конкатенирует их в текст запроса на место плейсхолдеров, и затем передаёт полученный текст запроса на MySQL. Самого обычного запроса. То есть это вовсе даже не серверный prepared statement, а его эмуляция на стороне клиента.
Но проблема в том, что Manticore Search - не MySQL. И он выполняет разнообразные экранирования по своему разумению, а не так, как это понимает MySQL. Нет, я понимаю, что разработчики не лохи, исследовали исходники MySQL вдоль и поперёк, сто раз всё проверили. Но все мы люди, все человеки, а потому потенция ошибки остаётся. И я, к примеру, не знаю, как будет обработана специально созданная текстовая строка в какой-нибудь экзотической или вообще несуществующей кодировке. Вы готовы гарантировать, что невозможно создание такой строки, которая после обработки кодом Manticore и конкатенации в текст запроса создаст-таки инъекцию? Я лично - нет.
PS. К слову, стандартные подготовленные запросы в MySQL поддерживают исключительно скалярные параметры предопределённых типов, соответственно никакие списки не допускаются, ибо такого типа данных в MySQL просто нет.
PPS. Стандартный prepared statement в MySQL прекрасно защитит от инъекции, даже если передаваемые в EXECUTE значения параметров будут злонамеренно модифицированы где-то в середине при прохождении трафика от клиента. Тогда как реализация на клиенте от такого не защищает.
MySQL поддерживает два типа prepared statements. Один - это через протокол. Буквально, в бинарном протоколе есть подмножество команд, которые реализуют perepare, execute и опционально long_data. Через консольный mysql клиент "пощупать" их невозможно, он эти команды не шлёт. Но вот некоторые другие клиенты, как оказалось, буквально ВСЮ работу делают через prepared statements. Даже какой-нибудь "show status" они шлют как prepare + execute + delete prepared. Собственно, именно эта часть протокола и реализована.
А то, о чём вы говорите - это другой тип, "синтаксический сахар" поверх обычного текстового протокола. Этот тип не поддерживается, и его не реализовывали.
Повторю ещё раз:
стандартные подготовленные запросы в MySQL поддерживают исключительно скалярные параметры предопределённых типов, соответственно никакие списки не допускаются, ибо такого типа данных в MySQL просто нет. ,
В статье же рассказывается о вставке списка в текст. Через подготовленные запросы MySQL этого не сделать - хоть в текстовой форме, хоть через протокол, о котором вы говорите. То есть список вставляется в текст запроса до отправки на сервер БД - другого варианта осуществить такую вставку я не вижу. Нет, если говорить строго, то существует ненулевая вероятность, что в протоколе такая возможность есть, а из текстовой формы нет - но вы не представляете, как такое мне лично сомнительно..
А что самое неприятное - то, что автор статьи в очень неуверенной форме говорит: "Корректный ввод состоит только из чисел, запятых и пробелов; любые другие символы, скорее всего, вызовут ошибку". Я это понимаю однозначно - может и не вызвать. А дальше можно накрутить и до инъекции.
К слову, у MySQL есть такая штука как General Log. Если его включить, то мы увидим все поступившие на MySQl запросы, причём строго в той форме, в какой они поступили. Если бы автор статьи озаботился получением этих данных, вопросов, непониманий и разночтений бы возникало куда как меньше.
Вот автор пишет:
Этот код подготавливает запрос
INSERT, привязывает строковые значения для названия и описания товара, а затем выполняет запрос. SQL, который в итоге выполнит Manticore, будет выглядеть так
Вот откуда он этот текст запроса взял? придумал? прикинул, как оно должно быть? вычитал из лога? Вот если бы в логе по показанному коду мы увидели показанный запрос, можно бы было смело утверждать, что prepared statement в Manticore есть эмуляция и фикция. А сейчас есть только вульгарное "а хрен знает"...

Prepared statements в Manticore Search