MySQL PHP PDO подготовил заявления – проблемы производительности и безопасности

Я думаю о переписывании приложения с открытым исходным кодом для моих целей в PDO и транзакциях с использованием InnoDB (mysql_query и MyISAM сейчас).

Мой вопрос: какие случаи разумны для использования подготовленных заявлений?

Потому что везде, где я читаю, говорится (даже во многих сообщениях здесь), что я должен использовать подготовленные заявления каждый раз и везде из-за 1. безопасности и 2. производительности. Даже руководство по PHP рекомендует использовать подготовленные заявления и не упоминать об исключении.

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

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

Я обнаружил, что этот mysql_real_escape называется $ pdo-> quote, а также для одного запроса. Почему бы не использовать это? Зачем беспокоиться о подготовке?

И что вы думаете об этой замечательной статье? http://blog.ulf-wendel.de/2008/pdo_mysqlnd-prepared-statements-again/

Согласны ли вы с накладными расходами, вызванными подготовкой заявлений?

благодаря

Я думаю, что это относится к категории «преждевременной оптимизации».

Насколько значительны накладные расходы? Вы это оценили? Это влияет на производительность вашего сервера вообще?

Скорее всего, нет.


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

С другой стороны, вы рискуете, что это может повлиять на производительность. В приведенной ссылке это показывает, что плохо реализованная подготовка PDO приводит к немного более низкой производительности, чем не подготовленная заявка в некоторых случаях. Разница в производительности на 5000 прогонов составляет 0,298 секунды.

Незначительный. Тем более, когда вы понимаете, что «не подготовленные» запросы выполняются без подпрограмм ввода, которые необходимы для обеспечения безопасности в живой среде. Если вы не используете подготовленные запросы, вам нужна некоторая форма дезактивации входных данных, чтобы предотвратить атаки SQL, и в зависимости от того, как это делается, вам может понадобиться массажировать результирующие наборы.

Итог, нет существенной проблемы с производительностью, но есть существенное преимущество в плане безопасности. Таким образом, официальная рекомендация использовать подготовленные заявления.

В вашем вопросе вы говорите о «общем eshop». В «общем eshop» никогда не будет достаточно трафика, чтобы беспокоиться о проблеме производительности, если таковая имеется. Проблема безопасности на другом конце …

Мой вопрос: какие случаи разумны для использования подготовленных заявлений?

Все они. Сообщество открыто выступает против использования функций mysql_* .

Примечание: Предлагаемые альтернативы

Использование этого расширения не рекомендуется. Вместо этого следует использовать расширение MySQLi или PDO_MySQL. См. Также MySQL: выбирая API для получения дополнительной информации.

Альтернативы этой функции включают:

  • mysqli_connect()
  • PDO::__construct()

источник

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

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

Я обнаружил, что этот mysql_real_escape называется $ pdo-> quote, а также для одного запроса. Почему бы не использовать это? Зачем беспокоиться о подготовке?

Если вы используете эту функцию для создания операторов SQL, настоятельно рекомендуется использовать PDO :: prepare () для подготовки операторов SQL с привязанными параметрами вместо использования PDO :: quote () для интерполяции ввода пользователя в инструкцию SQL. Подготовленные утверждения со связанными параметрами не только более переносимы, более удобны, невосприимчивы к SQL-инъекции, но часто выполняются намного быстрее, чем интерполированные запросы, так как сервер и клиентская сторона могут кэшировать скомпилированную форму запроса. источник

Мой вопрос: какие случаи разумны для использования подготовленных заявлений?

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

Чтобы дать вам пример: для ультра-хромого приложения гостевой книги PDO с подготовленными операторами будет идеальным выбором, а также для 99% всех других приложений с открытым исходным кодом. Но для некоторых это действительно может иметь значение. Важная часть здесь: вы ничего не сказали о приложении.

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

Таким образом, вам либо нужно поделиться больше об этом «загадочном» приложении с открытым исходным кодом, о котором вы спрашиваете, или вам нужно рассказать нам, что именно вы хотели бы знать. Потому что в целом это просто: возьмите PDO. Но, в частности, существуют различия, поэтому вам нужно рассказать нам, какое приложение является конкретным, иначе ваш вопрос уже будет дан.

И, кстати, если приложение является стилем mysql_ *, гораздо проще просто заменить интерфейс mysqli_ *. Если бы вы действительно переписывали, даже просто для удовольствия, вы бы это видели.

Так что лучше добавить больше мяса здесь или жить с некоторыми неточными ответами.

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

Чтобы подвести итог всему ниже:

  • Да всегда используйте подготовительные заявления
  • Да использовать PDO над mysqli над mysql. Таким образом, если вы переключаете системы баз данных, все, что вам нужно сделать, это обновлять запросы вместо запросов, вызовов функций и аргументов, учитывая, что они поддерживают подготовленные операторы.
  • Всегда дезинфицируйте предоставленные пользователем данные, несмотря на использование подготовленных операторов с параметрами
  • Изучите DBAL (уровень абстракции базы данных), чтобы облегчить работу со всеми этими факторами и манипулировать запросами в соответствии с вашими потребностями.

Существует тема PDO :: ATTR_EMULATE_PREPARES, которая увеличит производительность вызова кешированных запросов в MySQL> = 5.1.21, когда эмуляция отключена, которая по умолчанию включена. Значение PHP будет эмулировать подготовку перед выполнением, отправляет ее в фактическую базу данных. Время между эмулированными и неэмулируемыми обычно незначительно, если не работает с внешней базой данных (а не с локальным хостом), например, в облаке, которая может иметь аномально высокий уровень пинга.

Кэширование зависит от ваших настроек MySQL в my.cnf, но оптимизация MySQL выходит за рамки этой публикации.

 <?php $pdo = new \PDO($connection_string); $pdo->setAttribute( \PDO::ATTR_EMULATE_PREPARES, false ); ?> 

Поэтому имейте это в виду, поскольку mysqli_ не предоставляет API для эмуляции клиентской стороны и всегда будет использовать MySQL для подготовки операторов. http://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php

Несмотря на аналогичные функции, есть различия, и вам могут потребоваться функции, которые предоставляет один API, а другой – нет. См. Ссылку PHP по выбору одного API по другому: http://www.php.net/manual/en/mysqlinfo.api.choosing.php

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

Независимо от того, нет ли реальных преимуществ производительности в мире от использования подготовки или нет.

Другое преимущество подготовленных операторов работает с транзакциями, если вы используете InnoDB для MySQL. Вы можете начать транзакцию, вставить запись, получить последний идентификатор вставки, обновить другую таблицу, удалить из другого, и если что-то не удастся по пути, которым вы можете rollBack () до транзакции. В противном случае скопируйте изменения, если вы решите. Например, работая с новым порядком и установив последний порядковый номер пользователя в новый идентификатор заказа и удалив отложенный ордер, но указанный тип оплаты не соответствует критериям размещения заказов из таблицы order_flags, поэтому вы можете rollBack () и показать пользователю дружественное сообщение об ошибке.

Что касается безопасности, я довольно озадачен, никто не затронул это. При отправке любых предоставленных пользователем данных в ЛЮБЮЮ систему, включая PHP и MySQL, дезинфицируйте и стандартизируйте ее. Да, подготовленные заявления действительно обеспечивают некоторую безопасность, когда дело доходит до выхода из данных, но это НЕ 100% доказательство пули.

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

Чтобы добавить к вышесказанному, вы должны изучить уровень абстракции базы данных, который использует PDO. Например, Doctrine DBAL: http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/query-builder.html

Дополнительные преимущества работы с DBAL + PDO заключаются в том, что

  • Вы можете стандартизировать и сократить объем работы, которую вы должны выполнить.
  • Помощь в дезинфекции предоставленных пользователем данных
  • Легко управлять сложными запросами
  • Использовать вложенные транзакции
  • Легко переключаться между базами данных
  • Ваш код становится более переносимым и полезным в других проектах

Например, я расширил PDO и переопределил методы query (), fetchAll () и fetch (), чтобы они всегда использовали подготовленные операторы и чтобы я мог писать инструкции SQL внутри fetch () или fetchAll () вместо того, чтобы писать все снова. НАПРИМЕР:

 <?php $pdo = new PDOEnhanced( $connection ); $pdo->fetchAll( "SELECT * FROM foo WHERE bar = 'hi'", PDO::FETCH_OBJ ); //would automatically provide $stmt = $pdo->prepare( "SELECT * FROM foo WHERE bar=?" ); $stmt->execute( array( 'hi' ) ); $resultSet = $stmt->fetchAll( PDO::FETCH_OBJ ) ?> 

Что касается людей, предлагающих этот стиль mysql_ *, гораздо проще просто заменить mysqli_ * API. Это не так. Большая часть функций mysql_ * была оставлена ​​или изменения аргументов в mysqli_ * См. http://php.net/manual/en/mysqli.summary.php

Однако вы можете получить конвертер, выпущенный Oracle для упрощения процесса: https://wikis.oracle.com/display/mysql/Converting+to+MySQLi

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