Aby odpowiedzieć na Twoje obawy:
MySQL> = 5.1.17 (lub> = 5.1.21 dla instrukcji PREPARE
i EXECUTE
) może używać przygotowanych instrukcji w pamięci podręcznej zapytań . Twoja wersja MySQL + PHP może więc używać przygotowanych instrukcji z pamięcią podręczną zapytań. Zwróć jednak uwagę na zastrzeżenia dotyczące buforowania wyników zapytań w dokumentacji MySQL. Istnieje wiele rodzajów zapytań, których nie można buforować lub które są bezużyteczne, mimo że są buforowane. Z mojego doświadczenia wynika, że pamięć podręczna zapytań i tak nie jest często bardzo korzystna. Zapytania i schematy wymagają specjalnej konstrukcji, aby maksymalnie wykorzystać pamięć podręczną. Często buforowanie na poziomie aplikacji i tak jest konieczne na dłuższą metę.
Natywne przygotowania nie mają żadnego znaczenia dla bezpieczeństwa. Pseudo przygotowane instrukcje będą nadal unikały wartości parametrów zapytania, zostanie to po prostu wykonane w bibliotece PDO z ciągami znaków zamiast na serwerze MySQL przy użyciu protokołu binarnego. Innymi słowy, ten sam kod PDO będzie równie podatny (lub niewrażliwy) na ataki polegające na wstrzykiwaniu, niezależnie od EMULATE_PREPARES
ustawień. Jedyna różnica polega na tym, gdzie następuje zamiana parametru - w przypadku EMULATE_PREPARES
, w bibliotece PDO; bez EMULATE_PREPARES
, występuje na serwerze MySQL.
Bez EMULATE_PREPARES
ciebie mogą pojawić się błędy składniowe w czasie przygotowania, a nie w czasie wykonywania; z EMULATE_PREPARES
was dostanie tylko błędy składniowe w czasie wykonywania, ponieważ PDO nie posiada zapytanie dać MySQL aż do czasu wykonania. Zauważ, że ma to wpływ na kod, który napiszesz ! Zwłaszcza jeśli używasz PDO::ERRMODE_EXCEPTION
!
Dodatkowa uwaga:
- Koszt a
prepare()
(przy użyciu przygotowanych instrukcji przygotowanych natywnie) prepare();execute()
może być trochę wolniejszy niż wysyłanie zwykłego zapytania tekstowego przy użyciu emulowanych gotowych instrukcji. W wielu systemach baz danych plan zapytań dla a prepare()
jest również buforowany i może być współdzielony z wieloma połączeniami, ale nie sądzę, aby MySQL to robił. Jeśli więc nie użyjesz ponownie przygotowanego obiektu instrukcji do wielu zapytań, ogólne wykonanie może być wolniejsze.
Na koniec uważam, że przy starszych wersjach MySQL + PHP należy emulować przygotowane instrukcje, ale w przypadku najnowszych wersji należy wyłączyć emulację.
Po napisaniu kilku aplikacji korzystających z PDO stworzyłem funkcję połączenia PDO, która ma, moim zdaniem, najlepsze ustawienia. Prawdopodobnie powinieneś użyć czegoś takiego lub dostosować preferowane ustawienia:
/**
* 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;
}