Вот о чем я читал до сих пор PDO::ATTR_EMULATE_PREPARES
:
- Эмуляция подготовки PDO лучше с точки зрения производительности, поскольку собственная подготовка MySQL обходит кеш запросов .
- Собственная подготовка MySQL лучше для безопасности (предотвращение SQL-инъекций) .
- Собственная подготовка MySQL лучше подходит для отчетов об ошибках .
Я больше не знаю, насколько правдивы эти утверждения. При выборе интерфейса MySQL меня больше всего беспокоит предотвращение внедрения SQL-кода. Вторая проблема - производительность.
В настоящее время мое приложение использует процедурный MySQLi (без подготовленных операторов) и довольно часто использует кеш запросов. Он редко повторно использует подготовленные операторы в одном запросе. Я начал переход к PDO для названных параметров и безопасности подготовленных операторов.
Я использую MySQL 5.1.61
иPHP 5.3.2
Оставить PDO::ATTR_EMULATE_PREPARES
включенным или нет? Есть ли способ обеспечить как производительность кеша запросов, так и безопасность подготовленных операторов?
Ответы:
Чтобы ответить на ваши вопросы:
MySQL> = 5.1.17 (или> = 5.1.21 для
PREPARE
иEXECUTE
заявления) могут использовать подготовленные заявления в кэше запросов . Таким образом, ваша версия MySQL + PHP может использовать подготовленные операторы с кешем запросов. Однако обратите внимание на предостережения относительно кеширования результатов запросов в документации MySQL. Есть много видов запросов, которые нельзя кэшировать или которые бесполезны, даже если они кэшированы. По моему опыту, кеш запросов в любом случае не очень важен. Запросы и схемы требуют специальной конструкции, чтобы максимально использовать кеш. Часто кеширование на уровне приложения в конечном итоге все равно необходимо.Собственная подготовка не имеет никакого значения для безопасности. Псевдо-подготовленные операторы по-прежнему будут экранировать значения параметров запроса, это будет просто выполняться в библиотеке PDO со строками, а не на сервере MySQL с использованием двоичного протокола. Другими словами, один и тот же код PDO будет одинаково уязвим (или не уязвим) для атак путем внедрения, независимо от ваших
EMULATE_PREPARES
настроек. Единственная разница в том, где происходит замена параметра - сEMULATE_PREPARES
, это происходит в библиотеке PDO; безEMULATE_PREPARES
, это происходит на сервере MySQL.Без этого
EMULATE_PREPARES
вы можете получить синтаксические ошибки во время подготовки, а не во время выполнения; withEMULATE_PREPARES
вы получите синтаксические ошибки только во время выполнения, потому что PDO не имеет запроса для передачи MySQL до времени выполнения. Обратите внимание, что это влияет на код, который вы напишете ! Особенно если пользуетесьPDO::ERRMODE_EXCEPTION
!Дополнительное соображение:
prepare()
(с использованием собственных подготовленных операторов), поэтомуprepare();execute()
запрос с собственными подготовленными операторами может быть немного медленнее, чем выдача простого текстового запроса с использованием эмулированных подготовленных операторов. Во многих системах баз данных план запроса для a такжеprepare()
кэшируется и может использоваться несколькими соединениями, но я не думаю, что MySQL делает это. Поэтому, если вы не используете повторно подготовленный объект оператора для нескольких запросов, ваше общее выполнение может быть медленнее.В качестве последней рекомендации я думаю, что для более старых версий MySQL + PHP вы должны эмулировать подготовленные операторы, но в ваших самых последних версиях вы должны отключить эмуляцию.
После написания нескольких приложений, использующих PDO, я создал функцию подключения PDO, которая, по моему мнению, имеет лучшие настройки. Вероятно, вам следует использовать что-то подобное или настроить свои предпочтительные настройки:
источник
mysql_real_escape_string
с многобайтовыми символами) все равно оставит один уязвимым для атак инъекций?mysql_real_escape_string
под капотом и последующих уязвимостей, которые могут возникнуть (в очень конкретных крайних случаях).Остерегайтесь отключения
PDO::ATTR_EMULATE_PREPARES
(включение нативной подготовки), когда ваш PHPpdo_mysql
не компилируетсяmysqlnd
.Поскольку old
libmysql
не полностью совместим с некоторыми функциями, это может привести к странным ошибкам, например:PDO::PARAM_INT
старших битов для 64-битных целых чисел при привязке как (0x12345678AB будет обрезано до 0x345678AB на 64-битной машине)LOCK TABLES
(выдаетSQLSTATE[HY000]: General error: 2030 This command is not supported in the prepared statement protocol yet
исключение)mysqlnd
или эмулированной подготовкой он автоматически выполняет эту работу за вас и не выходит из синхронизации с сервером mysql)Эти ошибки я обнаружил в своем простом проекте при миграции на другой сервер, который использовался
libmysql
дляpdo_mysql
модуля. Может багов гораздо больше, не знаю. Также я тестировал свежий 64-битный debian jessie, все перечисленные ошибки возникают, когда яapt-get install php5-mysql
, и исчезают, когда яapt-get install php5-mysqlnd
.Когда
PDO::ATTR_EMULATE_PREPARES
установлено значение true (по умолчанию) - этих ошибок не происходит, потому что PDO вообще не использует подготовленные операторы в этом режиме. Итак, если вы используетеpdo_mysql
на основеlibmysql
(подстрока «mysqlnd» не отображается в поле «Версия клиентского API»pdo_mysql
раздела в phpinfo) - отключать не следуетPDO::ATTR_EMULATE_PREPARES
.источник
Я бы отключил эмуляцию подготовки, поскольку вы используете 5.1, что означает, что PDO будет использовать встроенные функции подготовленных операторов.
http://php.net/manual/en/ref.pdo-mysql.php
Я отказался от MySQLi для PDO ради подготовленных именованных операторов и лучшего API.
Однако, чтобы сбалансировать, PDO работает незначительно медленнее, чем MySQLi, но об этом следует помнить. Я знал это, когда делал выбор и решил, что лучший API и использование отраслевого стандарта важнее, чем использование пренебрежимо быстрой библиотеки, которая связывает вас с конкретным движком. FWIW Я думаю, что команда PHP также благосклонно смотрит на PDO, а не на MySQLi в будущем.
источник
Я бы рекомендовал включить реальные
PREPARE
вызовы базы данных, так как эмуляция не улавливает все ... например, она подготовитINSERT;
!Выход
Я с радостью получу удар по производительности для кода, который действительно работает.
FWIW
Версия PHP: PHP 5.4.9-4ubuntu2.4 (cli)
Версия MySQL: 5.5.34-0ubuntu0
источник
prepare
выполнить работу, которую он должен. (Кроме того, я всегда предполагал, что синтаксический анализатор параметров на стороне клиента обязательно будет иметь собственные ошибки.)Я удивлен, что никто не упомянул одну из главных причин для отключения эмуляции. При включенной эмуляции PDO возвращает все целые числа и числа с плавающей запятой в виде строк . Когда вы выключаете эмуляцию, целые числа и числа с плавающей запятой в MySQL становятся целыми числами и числами с плавающей запятой в PHP.
Для получения дополнительной информации см. Принятый ответ на этот вопрос: PHP + PDO + MySQL: как мне вернуть целочисленные и числовые столбцы из MySQL как целые числа и числа в PHP? ,
источник
https://tech.michaelseiler.net/2016/07/04/dont-emulate-prepared-statements-pdo-mysql/
источник
Для записи
PDO :: ATTR_EMULATE_PREPARES = верно
Это могло вызвать неприятный побочный эффект. Он может возвращать значения типа int в виде строки.
PHP 7.4, pdo с mysqlnd.
Выполнение запроса с PDO :: ATTR_EMULATE_PREPARES = true
Столбец: id
Тип: целое число
Значение: 1
Выполнение запроса с PDO :: ATTR_EMULATE_PREPARES = false
Столбец: id
Тип: строка
Значение: «1»
В любом случае десятичные значения всегда возвращаются строкой, независимо от конфигурации :-(
источник