अपनी चिंताओं का जवाब देने के लिए:
MySQL> = 5.1.17 (या> PREPARE
और EXECUTE
स्टेटमेंट के लिए 5.1.21 ) क्वेरी कैश में तैयार स्टेटमेंट का उपयोग कर सकते हैं । तो MySQL + PHP का आपका संस्करण क्वेरी कैश के साथ तैयार स्टेटमेंट का उपयोग कर सकता है। हालाँकि, MySQL प्रलेखन में क्वेरी परिणामों के कैशिंग के लिए चेतावनी पर ध्यान दें। कई प्रकार के प्रश्न होते हैं जिन्हें कैश नहीं किया जा सकता है या जो कैश हो जाने के बावजूद बेकार हैं। मेरे अनुभव में क्वेरी कैश अक्सर एक बहुत बड़ी जीत नहीं है। कैश का अधिकतम उपयोग करने के लिए क्वेरी और स्कीमा को विशेष निर्माण की आवश्यकता होती है। लंबे समय में वैसे भी अक्सर एप्लिकेशन-स्तरीय कैशिंग आवश्यक होता है।
देशी तैयारी सुरक्षा के लिए कोई अंतर नहीं रखती है। छद्म-तैयार बयान अभी भी क्वेरी पैरामीटर मूल्यों से बचेंगे, यह बस पीडीओ लाइब्रेरी में किया जाएगा जो बाइनरी प्रोटोकॉल का उपयोग करके MySQL सर्वर पर इसके बजाय स्ट्रिंग्स के साथ होगा। दूसरे शब्दों में, समान पीडीओ कोड आपकी EMULATE_PREPARES
सेटिंग की परवाह किए बिना इंजेक्शन हमलों के लिए समान रूप से असुरक्षित (या कमजोर नहीं) होगा । एकमात्र अंतर वह है जहां पैरामीटर प्रतिस्थापन होता है - साथ EMULATE_PREPARES
, यह पीडीओ लाइब्रेरी में होता है; बिना EMULATE_PREPARES
, यह MySQL सर्वर पर होता है।
बिना EMULATE_PREPARES
आपको निष्पादित-समय के बजाय तैयारी के समय में वाक्यविन्यास त्रुटियां मिल सकती हैं; आपके साथ EMULATE_PREPARES
निष्पादन के समय केवल वाक्यविन्यास त्रुटियां होंगी क्योंकि पीडीओ के पास निष्पादन समय तक MySQL को देने के लिए कोई क्वेरी नहीं है। ध्यान दें कि यह आपके द्वारा लिखे गए कोड को प्रभावित करेगा ! खासकर यदि आप उपयोग कर रहे हैं PDO::ERRMODE_EXCEPTION
!
एक अतिरिक्त विचार:
- एक
prepare()
(देशी तैयार बयानों का उपयोग करते हुए) के लिए एक निश्चित लागत है, इसलिए prepare();execute()
देशी तैयार किए गए बयानों के साथ एक छोटे से धीमी हो सकती है, जो तैयार किए गए बयानों का उपयोग करके एक सादे पाठ्य क्वेरी को जारी करने से हो। कई डेटाबेस सिस्टम पर एक के लिए क्वेरी प्लान prepare()
को कैश किया जाता है और कई कनेक्शन के साथ साझा किया जा सकता है, लेकिन मुझे नहीं लगता कि MySQL ऐसा करता है। इसलिए यदि आप कई प्रश्नों के लिए अपने तैयार किए गए कथन ऑब्जेक्ट का पुन: उपयोग नहीं करते हैं, तो आपका संपूर्ण निष्पादन धीमा हो सकता है।
अंतिम सिफारिश के रूप में , मुझे लगता है कि MySQL + PHP के पुराने संस्करणों के साथ, आपको तैयार किए गए बयानों का अनुकरण करना चाहिए, लेकिन अपने हाल के संस्करणों के साथ आपको अनुकरण बंद कर देना चाहिए।
पीडीओ का उपयोग करने वाले कुछ ऐप लिखने के बाद, मैंने एक पीडीओ कनेक्शन फ़ंक्शन किया है, जो मुझे लगता है कि सबसे अच्छी सेटिंग्स हैं। आपको शायद कुछ इस तरह का उपयोग करना चाहिए या अपनी पसंदीदा सेटिंग्स से जुड़ना चाहिए:
/**
* 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;
}