Para responder a sus inquietudes:
MySQL> = 5.1.17 (o> = 5.1.21 para las declaraciones PREPARE
y EXECUTE
) puede usar declaraciones preparadas en la caché de consultas . Entonces, su versión de MySQL + PHP puede usar declaraciones preparadas con la caché de consultas. Sin embargo, tenga en cuenta las advertencias para almacenar en caché los resultados de las consultas en la documentación de MySQL. Hay muchos tipos de consultas que no se pueden almacenar en caché o que son inútiles aunque estén en caché. En mi experiencia, la caché de consultas no suele ser una gran ganancia de todos modos. Las consultas y los esquemas necesitan una construcción especial para aprovechar al máximo la caché. A menudo, el almacenamiento en caché a nivel de aplicación termina siendo necesario de todos modos a largo plazo.
Native se prepara no hace ninguna diferencia para la seguridad. Las declaraciones pseudopreparadas aún escaparán de los valores de los parámetros de consulta, solo se hará en la biblioteca PDO con cadenas en lugar de en el servidor MySQL utilizando el protocolo binario. En otras palabras, el mismo código PDO será igualmente vulnerable (o no vulnerable) a los ataques de inyección independientemente de su EMULATE_PREPARES
configuración. La única diferencia es dónde se produce el reemplazo del parámetro, con EMULATE_PREPARES
, ocurre en la biblioteca PDO; sin EMULATE_PREPARES
, ocurre en el servidor MySQL.
Sin EMULATE_PREPARES
él, puede obtener errores de sintaxis en el tiempo de preparación en lugar de en el tiempo de ejecución; con EMULATE_PREPARES
, solo obtendrá errores de sintaxis en el momento de la ejecución porque PDO no tiene una consulta para entregar a MySQL hasta el momento de la ejecución. ¡Tenga en cuenta que esto afecta el código que escribirá ! ¡Especialmente si estás usando PDO::ERRMODE_EXCEPTION
!
Una consideración adicional:
- Hay un costo fijo para a
prepare()
(usando declaraciones preparadas nativas), por lo queprepare();execute()
con declaraciones preparadas nativas puede ser un poco más lento que emitir una consulta de texto sin formato usando declaraciones preparadas emuladas. En muchos sistemas de bases de datos, el plan de consulta para a también prepare()
se almacena en caché y puede compartirse con múltiples conexiones, pero no creo que MySQL haga esto. Entonces, si no reutiliza su objeto de declaración preparado para múltiples consultas, su ejecución general puede ser más lenta.
Como recomendación final , creo que con versiones anteriores de MySQL + PHP, debería emular declaraciones preparadas, pero con sus versiones más recientes debería desactivar la emulación.
Después de escribir algunas aplicaciones que usan PDO, he creado una función de conexión PDO que tiene lo que creo que son las mejores configuraciones. Probablemente debería usar algo como esto o ajustar su configuración preferida:
/**
* Return PDO handle for a MySQL connection using supplied settings
*
* Tries to do the right thing with different php and mysql versions.
*
* @param array $settings with keys: host, port, unix_socket, dbname, charset, user, pass. Some may be omitted or NULL.
* @return PDO
* @author Francis Avila
*/
function connect_PDO($settings)
{
$emulate_prepares_below_version = '5.1.17';
$dsndefaults = array_fill_keys(array('host', 'port', 'unix_socket', 'dbname', 'charset'), null);
$dsnarr = array_intersect_key($settings, $dsndefaults);
$dsnarr += $dsndefaults;
// connection options I like
$options = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
);
// connection charset handling for old php versions
if ($dsnarr['charset'] and version_compare(PHP_VERSION, '5.3.6', '<')) {
$options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES '.$dsnarr['charset'];
}
$dsnpairs = array();
foreach ($dsnarr as $k => $v) {
if ($v===null) continue;
$dsnpairs[] = "{$k}={$v}";
}
$dsn = 'mysql:'.implode(';', $dsnpairs);
$dbh = new PDO($dsn, $settings['user'], $settings['pass'], $options);
// Set prepared statement emulation depending on server version
$serverversion = $dbh->getAttribute(PDO::ATTR_SERVER_VERSION);
$emulate_prepares = (version_compare($serverversion, $emulate_prepares_below_version, '<'));
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, $emulate_prepares);
return $dbh;
}