Как именно плейсхолдеры (подготовленные выражения) защищают от sql-инъекций?
Подготовленные выражения защищают от SQL-инъекций тем, что отделяют синтаксис запроса от значений параметров запроса. Суть любой SQL-инъекции - изменить синтаксис (текст, если угодно) запроса тем или иным образом. Если вы передаете текст запроса и параметры отдельно, не будет никакой возможности повлиять на синтаксис запроса из параметра запроса.
В случае поддержки со стороны СУБД, подтоговленные выражения PHP должны использовать возможности СУБД и передавать ей сначала текст запроса для компиляции, а уже потом, отдельно - параметры запроса.
Теоретически, проблемы могут быть только в случае, если prepared statements не поддерживаются самой СУБД и эмулируются PDO (т.е. на стороне скрипта, а не БД). Тогда косяки в реализации сборки конечного запроса могут сказаться на безопасности. В случае поддержки со стороны СУБД "реализовывать" просто напросто нечего - вы защищены от инъекций не за счет экранирования всего и вся, а за счет правильного подхода - никогда не смешивать сам запрос и его параметры.
Насколько мне известно, mysql уже давным-давно поддерживает prepared statements, поэтому не вижу смысла бояться их использовать. А даже если б это было не так, вероятность в том, что при ручной сборке запроса накосячите ВЫ - гораздо выше.UPDATE: полезнейший коммент на странице php.net/manual/ru/pdo.prepare.php:With PDO_MYSQL you need to remember about the PDO::ATTR_EMULATE_PREPARES option.
The default value is TRUE, like
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,true);
This means that no prepared statement is created with $dbh->prepare() call. With exec() call PDO replaces the placeholders with values itself and sends MySQL a generic query string.
The first consequence is that the call  $dbh->prepare('garbage');
reports no error. You will get an SQL error during the $dbh->exec() call.
The second one is the SQL injection risk in special cases, like using a placeholder for the table name.
The reason for emulation is a poor performance of MySQL with prepared statements. Emulation works significantly faster.
Так что да, есть доля внезапности в поведении PDO. Я думаю стоит порыть инфы о настройке PDO::ATTR_EMULATE_PREPARES. Я считаю, что включать по-дефолту именно эмуляцию - это в высшей степени недальновидное решение. Проблемы MySQL затыкаются на стороне стандартной библиотеки языка....
За счет автоматического экранирования параметров.
php.net/manual/ru/pdo.prepared-statements.php