Ihre Anliegen zu beantworten:
MySQL> = 5.1.17 (oder> = 5.1.21 für die PREPARE
und EXECUTE
Aussagen) can use prepared statements in the query cache. Ihre Version von MySQL + PHP kann also vorbereitete Anweisungen mit dem Abfrage-Cache verwenden. Beachten Sie jedoch die Einschränkungen für die Zwischenspeicherung von Abfrageergebnissen in der MySQL-Dokumentation. Es gibt viele Arten von Abfragen, die nicht zwischengespeichert werden können oder die nutzlos sind, selbst wenn sie zwischengespeichert werden. Meiner Erfahrung nach ist der Abfrage-Cache sowieso nicht oft ein sehr großer Gewinn. Abfragen und Schemas benötigen eine spezielle Konstruktion, um den Cache optimal zu nutzen. Häufig ist auf lange Sicht das Caching auf Anwendungsebene ohnehin erforderlich.
Native Prepare macht keinen Unterschied für die Sicherheit. Die pseudo-vorbereiteten Anweisungen werden weiterhin Abfrageparameterwerten entgehen, sie werden nur in der PDO-Bibliothek mit Zeichenfolgen statt auf dem MySQL-Server, der das Binärprotokoll verwendet, ausgeführt. Mit anderen Worten, der gleiche 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 der Parameteraustausch stattfindet - mit EMULATE_PREPARES
tritt er in der PDO-Bibliothek auf; ohne EMULATE_PREPARES
tritt es auf dem MySQL-Server auf.
Ohne EMULATE_PREPARES
können Syntaxfehler bei der Vorbereitungszeit und nicht zur Ausführungszeit auftreten. Mit EMULATE_PREPARES
erhalten Sie nur Syntaxfehler zur Ausführungszeit, da PDO keine MySQL-Anfrage bis zur Ausführungszeit hat. Beachten Sie, dass dies den Code betrifft, den Sie schreiben werden! Vor allem, wenn Sie PDO::ERRMODE_EXCEPTION
verwenden!
Eine weitere Überlegung:
- Es gibt einen festen Preis für ein
prepare()
(unter Verwendung nativer Prepared Statements), so dass ein prepare();execute()
mit nativer vorbereiteten Anweisungen können ein wenig langsamer sein als eine einfache Text Abfrage ausgeben emulierte vorbereitete Anweisungen verwenden. Auf vielen Datenbanksystemen ist der Abfrageplan für eine prepare()
ebenfalls zwischengespeichert und kann mit mehreren Verbindungen geteilt werden, aber ich glaube nicht, dass MySQL dies tut. Wenn Sie das vorbereitete Anweisungsobjekt nicht für mehrere Abfragen verwenden, ist die Gesamtausführung möglicherweise langsamer.
Als abschließende Empfehlung, ich denke, mit älteren Versionen von MySQL + PHP, sollten Sie vorbereitete Anweisungen emulieren, aber mit Ihren jüngsten Versionen sollten Sie Emulation ausschalten.
Nachdem ich ein paar Apps geschrieben habe, die PDO verwenden, habe ich eine PDO-Verbindungsfunktion eingerichtet, die meiner Meinung nach die besten Einstellungen hat. Sie sollten wahrscheinlich so etwas wie diese oder zwicken, um Ihre bevorzugten Einstellungen verwenden:
/**
* 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;
}
Ehrlich? Benutze einfach MySQLi. Wenn es bereits mit vorbereiteten Anweisungen arbeitet, ist PDO im Grunde eine sinnlose Abstraktionsschicht. * EDIT *: PDO ist wirklich nützlich für Anwendungen im grünen Bereich, wo Sie nicht sicher sind, welche Datenbank in das Backend geht. – jmkeyes
Sorry, meine Frage war vorher unklar. Ich habe es bearbeitet. Die Anwendung verwendet zur Zeit keine vorbereiteten Anweisungen in MySQLi. nur mysqli_run_query(). Nach dem, was ich gelesen habe, umgehen MySQLi vorbereitete Anweisungen auch den Abfrage-Cache. –