Um Ihre Bedenken zu beantworten:
MySQL> = 5.1.17 (oder> = 5.1.21 für die Anweisungen PREPARE
und EXECUTE
) kann vorbereitete Anweisungen im Abfragecache verwenden . Ihre Version von MySQL + PHP kann also vorbereitete Anweisungen mit dem Abfragecache verwenden. Beachten Sie jedoch die Einschränkungen beim 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 sind. Nach meiner Erfahrung ist der Abfrage-Cache sowieso nicht oft ein großer Gewinn. Abfragen und Schemata erfordern eine spezielle Konstruktion, um den Cache maximal zu nutzen. Oft ist Caching auf Anwendungsebene auf lange Sicht ohnehin notwendig.
Native Vorbereitungen machen keinen Unterschied für die Sicherheit. Die pseudo-vorbereiteten Anweisungen entziehen sich weiterhin den Abfrageparameterwerten. Sie werden nur in der PDO-Bibliothek mit Zeichenfolgen anstatt auf dem MySQL-Server unter Verwendung des Binärprotokolls ausgeführt. Mit anderen Worten, derselbe PDO-Code ist unabhängig von Ihrer EMULATE_PREPARES
Einstellung gleichermaßen anfällig (oder nicht anfällig) für Injektionsangriffe . Der einzige Unterschied besteht darin, wo die Parameterersetzung erfolgt - mit EMULATE_PREPARES
, in der PDO-Bibliothek; ohne EMULATE_PREPARES
tritt es auf dem MySQL-Server auf.
Ohne EMULATE_PREPARES
können Syntaxfehler eher zur Vorbereitungszeit als zur Ausführungszeit auftreten. Mit erhalten EMULATE_PREPARES
Sie nur zur Ausführungszeit Syntaxfehler, da PDO bis zur Ausführungszeit keine Abfrage an MySQL senden muss. Beachten Sie, dass dies Auswirkungen auf den Code hat, den Sie schreiben werden ! Besonders wenn Sie verwenden PDO::ERRMODE_EXCEPTION
!
Eine zusätzliche Überlegung:
- Es gibt feste Kosten für a
prepare()
(unter Verwendung nativer vorbereiteter Anweisungen), daher kann a prepare();execute()
mit nativen vorbereiteten Anweisungen etwas langsamer sein als die Ausgabe einer einfachen Textabfrage unter Verwendung emulierter vorbereiteter Anweisungen. Auf vielen Datenbanksystemen wird der Abfrageplan für a ebenfalls prepare()
zwischengespeichert und kann für mehrere Verbindungen freigegeben werden, aber ich glaube nicht, dass MySQL dies tut. Wenn Sie Ihr vorbereitetes Anweisungsobjekt also nicht für mehrere Abfragen wiederverwenden, ist Ihre Gesamtausführung möglicherweise langsamer.
Als letzte Empfehlung denke ich, dass Sie mit älteren Versionen von MySQL + PHP vorbereitete Anweisungen emulieren sollten, aber mit Ihren neuesten Versionen sollten Sie die Emulation deaktivieren.
Nachdem ich einige Apps geschrieben habe, die PDO verwenden, habe ich eine PDO-Verbindungsfunktion erstellt, die meiner Meinung nach die besten Einstellungen aufweist. 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;
}