Um Ihre Bedenken zu beantworten:
-
MySQL>=5.1.17 (oder>=5.1.21 für
PREPARE
undEXECUTE
Anweisungen) können vorbereitete Anweisungen im Abfrage-Cache verwenden . Ihre Version von MySQL+PHP kann also vorbereitete Anweisungen mit dem Abfrage-Cache verwenden. Beachten Sie jedoch sorgfältig die Vorbehalte zum Zwischenspeichern von Abfrageergebnissen in der MySQL-Dokumentation. Es gibt viele Arten von Abfragen, die nicht zwischengespeichert werden können oder die nutzlos sind, obwohl sie zwischengespeichert werden. Meiner Erfahrung nach ist der Abfrage-Cache sowieso nicht oft ein großer Gewinn. Abfragen und Schemas müssen speziell konstruiert werden, um den Cache optimal zu nutzen. Oft wird das Caching auf Anwendungsebene auf lange Sicht ohnehin notwendig. -
Native Vorbereitungen machen keinen Unterschied für die Sicherheit. Die pseudo-vorbereiteten Anweisungen werden immer noch Abfrageparameterwerte maskieren, es wird nur in der PDO-Bibliothek mit Strings statt auf dem MySQL-Server unter Verwendung des Binärprotokolls durchgeführt. Mit anderen Worten, derselbe PDO-Code ist unabhängig von Ihrem
EMULATE_PREPARES
gleichermaßen anfällig (oder nicht anfällig) für Injektionsangriffe Einstellung. Der einzige Unterschied besteht darin, wo die Parameterersetzung erfolgt – mitEMULATE_PREPARES
, es kommt in der PDO-Bibliothek vor; ohneEMULATE_PREPARES
, es tritt auf dem MySQL-Server auf. -
Ohne
EMULATE_PREPARES
Möglicherweise erhalten Sie Syntaxfehler eher zur Vorbereitungszeit als zur Ausführungszeit. mitEMULATE_PREPARES
Sie erhalten nur zur Ausführungszeit Syntaxfehler, da PDO bis zur Ausführungszeit keine Abfrage an MySQL geben muss. Beachten Sie, dass dies den Code beeinflusst, den Sie schreiben werden ! Besonders wenn SiePDO::ERRMODE_EXCEPTION
verwenden !
Eine zusätzliche Überlegung:
- Für ein
prepare()
fallen feste Kosten an (unter Verwendung nativer vorbereiteter Anweisungen), also einprepare();execute()
mit nativen vorbereiteten Anweisungen kann etwas langsamer sein als das Ausgeben einer einfachen Textabfrage mit emulierten vorbereiteten Anweisungen. Auf vielen Datenbanksystemen ist der Abfrageplan für einprepare()
wird ebenfalls zwischengespeichert und kann mit mehreren Verbindungen geteilt werden, aber ich glaube nicht, dass MySQL dies tut. Wenn Sie also Ihr vorbereitetes Anweisungsobjekt nicht für mehrere Abfragen wiederverwenden, kann Ihre Gesamtausführung langsamer sein.
Als letzte Empfehlung , denke ich, dass Sie mit älteren Versionen von MySQL+PHP vorbereitete Anweisungen emulieren sollten, aber mit Ihren allerneuesten Versionen sollten Sie die Emulation ausschalten.
Nachdem ich einige Apps geschrieben habe, die PDO verwenden, habe ich eine PDO-Verbindungsfunktion erstellt, die meiner Meinung nach die besten Einstellungen hat. Sie sollten wahrscheinlich so etwas verwenden oder Ihre bevorzugten Einstellungen anpassen:
/**
* 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;
}