Per rispondere alle tue preoccupazioni:
MySQL> = 5.1.17 (o> = 5.1.21 per le istruzioni PREPARE
e EXECUTE
) può utilizzare istruzioni preparate nella cache delle query . Quindi la tua versione di MySQL + PHP può utilizzare istruzioni preparate con la cache delle query. Tuttavia, prendi nota delle avvertenze per la memorizzazione nella cache dei risultati delle query nella documentazione di MySQL. Esistono molti tipi di query che non possono essere memorizzate nella cache o che sono inutili anche se vengono memorizzate nella cache. Nella mia esperienza, la cache delle query non è spesso una grande vittoria comunque. Le query e gli schemi richiedono una costruzione speciale per sfruttare al massimo la cache. Spesso la memorizzazione nella cache a livello di applicazione finisce per essere necessaria comunque a lungo termine.
La preparazione nativa non fa alcuna differenza per la sicurezza. Le istruzioni pseudo-preparate continueranno a sfuggire ai valori dei parametri di query, verrà semplicemente eseguita nella libreria PDO con stringhe invece che sul server MySQL utilizzando il protocollo binario. In altre parole, lo stesso codice PDO sarà ugualmente vulnerabile (o non vulnerabile) agli attacchi di iniezione indipendentemente dalle EMULATE_PREPARES
impostazioni. L'unica differenza è dove avviene la sostituzione dei parametri - con EMULATE_PREPARES
, avviene nella libreria PDO; senza EMULATE_PREPARES
, si verifica sul server MySQL.
Senza di EMULATE_PREPARES
te potresti ottenere errori di sintassi in fase di preparazione piuttosto che in fase di esecuzione; con EMULATE_PREPARES
si otterranno solo errori di sintassi al momento dell'esecuzione perché PDO non ha una query da dare a MySQL fino al momento dell'esecuzione. Nota che questo influisce sul codice che scriverai ! Soprattutto se stai usando PDO::ERRMODE_EXCEPTION
!
Un'ulteriore considerazione:
- C'è un costo fisso per a
prepare()
(utilizzando istruzioni preparate native), quindi a prepare();execute()
con istruzioni preparate native potrebbe essere un po 'più lento rispetto al rilascio di una semplice query testuale utilizzando istruzioni preparate emulate. Su molti sistemi di database anche il piano di query per a prepare()
è memorizzato nella cache e può essere condiviso con più connessioni, ma non credo che MySQL lo faccia. Quindi, se non riutilizzi il tuo oggetto istruzione preparato per più query, la tua esecuzione complessiva potrebbe essere più lenta.
Come raccomandazione finale , penso che con le versioni precedenti di MySQL + PHP, dovresti emulare le istruzioni preparate, ma con le tue versioni molto recenti dovresti disattivare l'emulazione.
Dopo aver scritto alcune app che utilizzano PDO, ho creato una funzione di connessione PDO che ha quelle che penso siano le impostazioni migliori. Probabilmente dovresti usare qualcosa di simile o modificare le tue impostazioni preferite:
/**
* 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;
}