Folgendes habe ich bisher gelesen PDO::ATTR_EMULATE_PREPARES
:
- Die Vorbereitungsemulation von PDO ist für die Leistung besser, da die native Vorbereitung von MySQL den Abfragecache umgeht .
- Die native Vorbereitung von MySQL ist aus Sicherheitsgründen besser (verhindert SQL Injection) .
- Die native Vorbereitung von MySQL eignet sich besser für die Fehlerberichterstattung .
Ich weiß nicht mehr, wie wahr eine dieser Aussagen ist. Mein größtes Anliegen bei der Auswahl einer MySQL-Schnittstelle ist die Verhinderung von SQL Injection. Das zweite Problem ist die Leistung.
Meine Anwendung verwendet derzeit prozedurales MySQLi (ohne vorbereitete Anweisungen) und verwendet den Abfrage-Cache ziemlich oft. Vorbereitete Anweisungen werden selten in einer einzigen Anforderung wiederverwendet. Ich habe die Umstellung auf PDO für die genannten Parameter und die Sicherheit der vorbereiteten Anweisungen gestartet.
Ich benutze MySQL 5.1.61
undPHP 5.3.2
Soll ich PDO::ATTR_EMULATE_PREPARES
aktiviert lassen oder nicht? Gibt es eine Möglichkeit, sowohl die Leistung des Abfragecaches als auch die Sicherheit vorbereiteter Anweisungen zu gewährleisten?
Antworten:
Um Ihre Bedenken zu beantworten:
MySQL> = 5.1.17 (oder> = 5.1.21 für die Anweisungen
PREPARE
undEXECUTE
) 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 - mitEMULATE_PREPARES
, in der PDO-Bibliothek; ohneEMULATE_PREPARES
tritt es auf dem MySQL-Server auf.Ohne
EMULATE_PREPARES
können Syntaxfehler eher zur Vorbereitungszeit als zur Ausführungszeit auftreten. Mit erhaltenEMULATE_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 verwendenPDO::ERRMODE_EXCEPTION
!Eine zusätzliche Überlegung:
prepare()
(unter Verwendung nativer vorbereiteter Anweisungen), daher kann aprepare();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 ebenfallsprepare()
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:
quelle
mysql_real_escape_string
mit Multi-Byte-Zeichen) einen für Injektionsangriffe offen lässt.mysql_real_escape_string
unter der Haube und die daraus resultierenden Schwachstellen, die auftreten können (in ganz bestimmten Randfällen).Achten Sie beim Deaktivieren
PDO::ATTR_EMULATE_PREPARES
(Aktivieren der nativen Vorbereitungen) darauf, dass Ihr PHPpdo_mysql
nicht kompiliert wirdmysqlnd
.Da old
libmysql
mit einigen Funktionen nicht vollständig kompatibel ist, kann es zu seltsamen Fehlern kommen, zum Beispiel:PDO::PARAM_INT
(0x12345678AB wird auf einem 64-Bit-Computer auf 0x345678AB zugeschnitten)LOCK TABLES
(es löst eineSQLSTATE[HY000]: General error: 2030 This command is not supported in the prepared statement protocol yet
Ausnahme aus)mysqlnd
oder emuliert wird dies automatisch für Sie erledigt und nicht nicht mehr mit dem MySQL-Server synchronisiert).Diese Fehler habe ich in meinem einfachen Projekt herausgefunden, als ich auf einen anderen Server migriert habe, der
libmysql
für daspdo_mysql
Modul verwendet wurde. Vielleicht gibt es noch viel mehr Fehler, ich weiß es nicht. Auch ich habe auf frischem 64bit Debian Jessie getestet, alle aufgelisteten Bugs treten auf, wenn ichapt-get install php5-mysql
, und verschwinden, wenn ichapt-get install php5-mysqlnd
.Wann
PDO::ATTR_EMULATE_PREPARES
ist auf true gesetzt (standardmäßig) - diese Fehler treten ohnehin nicht auf, da PDO in diesem Modus überhaupt keine vorbereiteten Anweisungen verwendet. Wenn Sie alsopdo_mysql
basierend auf verwendenlibmysql
("mysqlnd" Teilzeichenfolge erscheint nicht im Feld "Client API Version" despdo_mysql
Abschnitts in phpinfo) - sollten Sie nicht deaktivierenPDO::ATTR_EMULATE_PREPARES
.quelle
Ich würde Emulate-Vorbereitungen deaktivieren, während Sie 5.1 ausführen, was bedeutet, dass PDO die native Funktionalität für vorbereitete Anweisungen nutzt.
http://php.net/manual/en/ref.pdo-mysql.php
Ich habe MySQLi für PDO wegen der vorbereiteten benannten Anweisungen und der besseren API über Bord geworfen.
Um ausgeglichen zu sein, arbeitet PDO vernachlässigbar langsamer als MySQLi, aber es ist etwas zu beachten. Ich wusste das, als ich die Wahl traf, und entschied, dass eine bessere API und die Verwendung des Industriestandards wichtiger sind als die Verwendung einer vernachlässigbar schnelleren Bibliothek, die Sie an eine bestimmte Engine bindet. FWIW Ich denke, das PHP-Team sieht PDO gegenüber MySQLi auch für die Zukunft positiv.
quelle
Ich würde empfehlen, echte Datenbankaufrufe zu aktivieren,
PREPARE
da die Emulation nicht alles abfängt. Zum Beispiel wird sie vorbereitetINSERT;
!Die Ausgabe
Ich nehme gerne einen Performance-Hit für Code, der tatsächlich funktioniert.
FWIW
PHP-Version: PHP 5.4.9-4ubuntu2.4 (cli)
MySQL Version: 5.5.34-0ubuntu0
quelle
prepare
den Job machen zu lassen , den es soll. (Außerdem habe ich immer angenommen, dass der clientseitige Parameterparser notwendigerweise eigene Fehler aufweist.)https://tech.michaelseiler.net/2016/07/04/dont-emulate-prepared-statements-pdo-mysql/
quelle
Ich bin überrascht, dass niemand einen der Hauptgründe für das Deaktivieren der Emulation genannt hat. Bei aktivierter Emulation gibt PDO alle Ganzzahlen zurück und schwebt als Zeichenfolgen . Wenn Sie die Emulation deaktivieren, werden Ganzzahlen und Gleitkommazahlen in MySQL zu Ganzzahlen und Gleitkommazahlen in PHP.
Weitere Informationen finden Sie in der akzeptierten Antwort auf diese Frage: PHP + PDO + MySQL: Wie gebe ich in PHP ganzzahlige und numerische Spalten aus MySQL als Ganzzahlen und Zahlen zurück? .
quelle
Für die Aufzeichnung
PDO :: ATTR_EMULATE_PREPARES = true
Es könnte eine böse Nebenwirkung erzeugen. Es könnte int-Werte als Zeichenfolge zurückgeben.
PHP 7.4, pdo mit mysqlnd.
Ausführen einer Abfrage mit PDO :: ATTR_EMULATE_PREPARES = true
Spalte: id
Typ: Ganzzahl
Wert: 1
Ausführen einer Abfrage mit PDO :: ATTR_EMULATE_PREPARES = false
Spalte: id
Typ: Zeichenfolge
Wert: "1"
In jedem Fall werden Dezimalwerte unabhängig von der Konfiguration immer als Zeichenfolge zurückgegeben :-(
quelle