Pour répondre à vos préoccupations:
MySQL >= 5.1.17 (ou >= 5.1.21 pour l' PREPARE
et EXECUTE
des déclarations) peut utiliser les requêtes préparées dans le cache de requêtes. Si votre version de MySQL+PHP peut utiliser des requêtes préparées avec le cache de requêtes. Cependant, note soigneusement les mises en garde pour la mise en cache résultats de la requête dans la documentation de MySQL. Il existe de nombreux types de requêtes qui ne peuvent pas être mis en cache ou qui sont inutiles, même si elles sont mises en cache. Dans mon expérience, la mise en cache de requêtes n'est pas souvent une très grande victoire, de toute façon. Des requêtes et schémas besoin spécial de construction pour faire une utilisation maximale de la mémoire cache. Souvent au niveau de l'application de la mise en cache finit par être nécessaire de toute façon dans le long terme.
Natif prépare ne fait aucune différence pour la sécurité. Le pseudo-préparées vont encore s'échapper de valeurs de paramètres de requête, il suffit de faire dans la librairie PDO avec des chaînes au lieu de le faire sur le serveur MySQL en utilisant le protocole binaire. En d'autres termes, la même AOP code sera tout aussi vulnérables (ou non-vulnérable à des attaques par injection, quel que soit votre EMULATE_PREPARES
réglage. La seule différence est l'emplacement du paramètre de remplacement se produit-- EMULATE_PREPARES
, il se produit dans la librairie PDO; sans EMULATE_PREPARES
, il se produit sur le serveur MySQL.
Sans EMULATE_PREPARES
vous pouvez obtenir des erreurs de syntaxe à préparer en temps plutôt qu'à exécuter en temps; avec EMULATE_PREPARES
, vous obtiendrez uniquement des erreurs de syntaxe lors de l'exécution parce que PDO n'est pas question de donner à MySQL jusqu'à ce que le temps d'exécution. Notez que cela affecte le code que vous allez écrire! Surtout si vous utilisez PDO::ERRMODE_EXCEPTION
!
Une autre considération:
- Il y a un coût fixe pour un
prepare()
(en utilisant natif déclarations préparées à l'avance), donc un prepare();execute()
natif de déclarations préparées à l'avance peut être un peu plus lent que la délivrance d'une plaine textuelle requête à l'aide de émulé déclarations préparées à l'avance. Sur de nombreux systèmes de base de données le plan de requête pour un prepare()
est mis en cache et peuvent être partagées avec des connexions multiples, mais je ne pense pas que MySQL ne ce. Donc, si vous ne pas réutiliser votre déclaration d'objet de plusieurs requêtes de l'ensemble de votre exécution peut être plus lente.
Comme une recommandation finale, je pense qu'avec les anciennes versions de MySQL+PHP, vous devez imiter déclarations préparées à l'avance, mais avec votre des versions très récentes, vous devez tourner à l'émulation off.
Après avoir écrit quelques applications que l'utilisation de PDO, j'ai fait un AOP fonction de connexion qui a, je pense, ce sont les meilleurs réglages. Vous devriez utiliser quelque chose comme ceci ou modifier vos paramètres préférés:
/**
* 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;
}