Я думаю о переписывании приложения с открытым исходным кодом для моих целей в 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 :: 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% точным, поэтому проверяйте изменения перед их объединением. Он также добавит значительное количество накладных расходов для создаваемых глобальных переменных.