Endişelerinize cevap vermek için:
MySQL> = 5.1.17 (veya PREPARE
ve EXECUTE
ifadeleri için> = 5.1.21 ) sorgu önbelleğinde hazırlanmış ifadeleri kullanabilir . Böylece MySQL + PHP sürümünüz, sorgu önbelleği ile hazırlanmış ifadeleri kullanabilir. Ancak, sorgu sonuçlarını MySQL belgelerinde önbelleğe almak için uyarıları dikkatlice not edin. Önbelleğe alınamayan veya önbelleğe alınmış olsalar bile yararsız olan birçok sorgu türü vardır. Deneyimlerime göre, sorgu önbelleği genellikle çok büyük bir kazanç değildir. Önbellekten maksimum düzeyde yararlanmak için sorgular ve şemalar özel bir yapıya ihtiyaç duyar. Genellikle uygulama düzeyinde önbelleğe alma, uzun vadede zaten gerekli hale gelir.
Yerel hazırlıklar, güvenlik açısından herhangi bir fark yaratmaz. Sözde hazırlanmış ifadeler yine de sorgu parametresi değerlerinden kaçış sağlar, sadece ikili protokol kullanılarak MySQL sunucusu yerine dizelerle PDO kitaplığında yapılır. Başka bir deyişle, aynı PDO kodu, EMULATE_PREPARES
ayarınız ne olursa olsun, enjeksiyon saldırılarına karşı eşit derecede savunmasız (veya savunmasız) olacaktır . Tek fark, parametre değişiminin gerçekleştiği yerdir - ile EMULATE_PREPARES
, bu, PDO kitaplığında gerçekleşir; olmadan EMULATE_PREPARES
, MySQL sunucusunda gerçekleşir.
Olmazsa EMULATE_PREPARES
yürütme zamanı yerine hazırlık zamanında sözdizimi hataları alabilirsiniz; ile EMULATE_PREPARES
PDO yürütme zamanına kadar MySQL dağıtmak üzere bir sorgu yoktur senin yüzünden sadece yürütme anda dizimi hatalarının alacak. Bunun yazacağınız kodu etkilediğini unutmayın ! Özellikle kullanıyorsanız PDO::ERRMODE_EXCEPTION
!
Ek bir husus:
- A için sabit bir maliyet vardır
prepare()
(yerel olarak hazırlanmış ifadeler kullanarak), bu nedenle prepare();execute()
yerel olarak hazırlanmış ifadelerle, öykünülmüş hazırlanmış ifadeler kullanarak düz metinsel bir sorgu yayınlamaktan biraz daha yavaş olabilir. Birçok veritabanı sisteminde a için sorgu planı prepare()
da önbelleğe alınır ve birden çok bağlantıyla paylaşılabilir, ancak MySQL'in bunu yaptığını sanmıyorum. Dolayısıyla, hazırladığınız ifade nesnesini birden çok sorgu için yeniden kullanmazsanız, genel yürütme işleminiz daha yavaş olabilir.
Son bir öneri olarak , MySQL + PHP'nin eski sürümlerinde hazırlanmış ifadeleri taklit etmelisiniz, ancak çok yeni sürümlerinizle öykünmeyi kapatmalısınız.
PDO kullanan birkaç uygulama yazdıktan sonra, en iyi ayarların olduğunu düşündüğüm bir PDO bağlantı işlevi yaptım. Muhtemelen böyle bir şey kullanmalı veya tercih ettiğiniz ayarlara ince ayar yapmalısınız:
/**
* 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;
}