PDO समापन कनेक्शन


120

MySQLi की तुलना में PDO के संबंध में सिर्फ एक सरल प्रश्न है।

MySQLi के साथ, आपके द्वारा किए जा सकने वाले कनेक्शन को बंद करने के लिए:

$this->connection->close();

हालांकि पीडीओ के साथ यह बताता है कि आप कनेक्शन का उपयोग करते हैं:

$this->connection = new PDO();

लेकिन उस कनेक्शन को बंद करने के लिए जिसे आपने इसे सेट किया है null

$this->connection = null;

क्या यह सही है और क्या यह वास्तव में पीडीओ कनेक्शन को मुक्त करेगा? (मुझे पता है कि जैसा यह सेट होता है null।) मेरा मतलब है MySQLi के साथ आपको closeकनेक्शन बंद करने के लिए एक फ़ंक्शन ( ) कॉल करना होगा । क्या पीडीओ = nullकाटना आसान है ? या कनेक्शन बंद करने के लिए एक फ़ंक्शन है?


11
अगर मैं पूछ रहा हूं तो मुझे यकीन नहीं है कि मैं कनेक्शन ठीक से बंद कर रहा हूं। लेकिन नहीं वास्तव में सिर्फ साज़िश
Liam Sorsby

2
जब आपका PHP स्क्रिप्ट निष्पादन बंद कर देता है तो डेटाबेस कनेक्शन स्वचालित रूप से बंद हो जाता है।
मार्टिन बीन

3
यदि आप इसका उपयोग कर रहे हैं, तो आगे क्यों न जाएं और इसे समाप्त करें, खासकर यदि डेटाबेस के साथ बातचीत करने के बाद कुछ समय लेने वाला कोड हो। हालाँकि, मैं वास्तव में स्क्रिप्ट के इंतजार के साथ इस मुद्दे को नहीं देख रहा हूँ, हालांकि या तो (DB सर्वर से कनेक्शन को कम करने के अलावा)।
Kieran

3
github.com/php/php-src/blob/master/ext/pdo/pdo_dbh.c खुद के लिए जानें कि यह कैसे काम करता है: P
Flosculus

23
सभी php स्क्रिप्ट अल्पकालिक नहीं होती हैं। वहाँ php डेमॉन हैं। मुझे लगता है कि व्यक्तिगत रूप से स्पष्ट करने के लिए यह बहुत अच्छी बात है।
डाटयूसर

जवाबों:


146

प्रलेखन के अनुसार आप सही हैं ( http://php.net/manual/en/pdo.connections.php ):

कनेक्शन उस पीडीओ ऑब्जेक्ट के जीवनकाल के लिए सक्रिय रहता है । कनेक्शन को बंद करने के लिए, आपको यह सुनिश्चित करके ऑब्जेक्ट को नष्ट करना होगा कि इसके शेष सभी संदर्भ हटा दिए गए हैं - आप ऐसा करते हैं जो ऑब्जेक्ट को रखने वाले वैरिएबल को NULL असाइन करके। यदि आप स्पष्ट रूप से ऐसा नहीं करते हैं, तो आपकी स्क्रिप्ट समाप्त होने पर PHP स्वचालित रूप से कनेक्शन बंद कर देगी

ध्यान दें कि यदि आप एक सतत कनेक्शन के रूप में पीडीओ ऑब्जेक्ट को इनिशियलाइज़ करते हैं तो यह स्वचालित रूप से कनेक्शन को बंद नहीं करेगा।


4
क्या होगा यदि मेरे पास एक प्रक्रिया है जो समाप्त नहीं होती है? उदाहरण के लिए websocket। क्या लगातार कनेक्शन का उपयोग नहीं करने का एक तरीका है?
राफेल मोनी

1
लंबे समय तक चलने वाली स्क्रिप्ट में लगातार कनेक्शन के लिए आप जानबूझकर (या गलती से) एक टाइमआउट (जैसे my.ini), या कई अन्य कारणों से मारे गए कनेक्शन हो सकते हैं। किसी क्वेरी को कनेक्ट या रन करते समय, किसी भी त्रुटि को पकड़ें, और यदि यह "MySQL चला गया है", तो फिर से कनेक्ट करने या दूसरी बार क्वेरी चलाने का प्रयास करें।
फ्रैंक फोर्ट

1
Note that if you initialise the PDO object as a persistent connection it will not automatically close the connectionलेकिन अगर कोई कनेक्शन लगातार बना रहता है और स्क्रिप्ट खत्म होने से पहले मैं स्पष्ट रूप से NULL को कॉल करता हूं, तो यह लगातार बंद हो जाएगा, भले ही वह सही हो?
टोनिक्स

1
@tonix नहीं, इसे रिलीज़ किया जाना चाहिए (किसी अन्य स्क्रिप्ट के लिए उपलब्ध), लेकिन बंद नहीं।
बेंजामिन

2
@tonix मुझे ऐसा लगता है, हाँ। लगातार कनेक्शन पर PHP मैनुअल से उद्धरण : " चेतावनी लगातार कनेक्शन का उपयोग करते समय ध्यान में रखने के लिए कुछ अतिरिक्त चेतावनी हैं। एक यह है कि एक निरंतर कनेक्शन पर टेबल लॉकिंग का उपयोग करते समय, यदि स्क्रिप्ट जो भी कारण से लॉक जारी नहीं कर सकता है। उसी कनेक्शन का उपयोग करने वाली बाद की स्क्रिप्ट अनिश्चित काल के लिए ब्लॉक हो जाएंगी और इसके लिए आपको या तो httpd सर्वर या डेटाबेस सर्वर को पुनरारंभ करना पड़ सकता है। "
बेंजामिन

46
$conn=new PDO("mysql:host=$host;dbname=$dbname",$user,$pass);
    // If this is your connection then you have to assign null
    // to your connection variable as follows:
$conn=null;
    // By this way you can close connection in PDO.

11
IMHO मुझे लगता है कि यह एक बहुत ही बुरा पैटर्न है, खासकर जब एक डेवलपर पोडो संदर्भ की कई प्रतियां संग्रहीत कर सकता है। $ a = नया PDO (...); $ बी = $ ए; $ = एक अशक्त; वहां, आपकी पीडीओ वस्तु हमेशा के लिए खुली रहेगी (डेमन-जैसे php प्रोग्राम में)। यह विशेष रूप से सच है जब पीडीओ संदर्भ फ़ंक्शंस और ऑब्जेक्ट गुणों में यात्रा करता है, और आप उन सभी को शून्य करना सुनिश्चित नहीं करते हैं।
गेब्रियल

33
पीडीओ पर एक -> करीब () विधि होनी चाहिए।
गेब्रियल

5
पीडीओ को नापसंद करने का एक और कारण।
जोस कार्लोस PHP

6
@ गैब्रिएल - मेरा सुझाव है कि "कई प्रतियां संग्रहीत करना" एक और भी बदतर पैटर्न है।
रिक जेम्स

4
यह काम नहीं करता है यदि आपने उन दो पंक्तियों के बीच एक पीडीओएसटेटमेंट ऑब्जेक्ट बनाया है (जो कि प्रत्येक व्यावहारिक स्थिति में है)। कनेक्शन को बंद करने के लिए, आपको पीडीओ ऑब्जेक्ट और पीडीओएसटेटमेंट ऑब्जेक्ट को शून्य करने के लिए सेट करना होगा। : यहाँ देखें php.net/manual/en/pdo.connections.php#114822
Ilmari

8

यह नल को कनेक्शन स्थापित करने से अधिक है। यह वही हो सकता है जो प्रलेखन कहता है, लेकिन यह mysql के लिए सच्चाई नहीं है। कनेक्शन थोड़ी देर के लिए इधर-उधर रहेगा (Ive 60 के दशक सुना, लेकिन कभी भी इसका परीक्षण नहीं किया गया)

यदि आप यहां पूरी व्याख्या करना चाहते हैं, तो इस टिप्पणी को कनेक्शन पर देखें https://www.php.net/manual/en/pdo.connections.php#114822

कनेक्शन को बंद करने के लिए आपको कुछ करना होगा

$this->connection = new PDO();
$this->connection->query('KILL CONNECTION_ID()');
$this->connection = null;

आपके उत्तर के लिए धन्यवाद। सवाल काफी समय पहले से था लेकिन कनेक्शन के बारे में आपका अधिकार।
लियाम सोर्स्बी

मैं वास्तव में सहमत नहीं हूं कि PHP के माध्यम से टीसीपी कनेक्शन के साथ खिलवाड़ करना एक अच्छा विचार है। सभी निम्न स्तर के टीसीपी कनेक्शन की हैंडलिंग दूर होती है ताकि हमें रनटाइम के दौरान उच्च स्तर की क्लास और ऑब्जेक्ट्स से निपटना पड़े। PHP एक अनुरोध आधारित भाषा है (जैसा कि आप शायद जानते हैं) इसलिए dB के लिए संभावित रूप से लगातार कनेक्शन को मारने से उपयोगकर्ताओं के लिए अनपेक्षित त्रुटियों / मुद्दों का परिणाम होगा। आपके द्वारा लिंक किया गया उपयोग का मामला ड्राइवर के लिए एक अन्य अनुरोध द्वारा उपयोग किए जा रहे स्थायी कनेक्शन को खुला रखने की संभावना है, इसलिए मुझे लगा कि यह अपेक्षित व्यवहार होगा।
लियाम सोर्स्बी

यदि आप वास्तव में mysql में प्रक्रियाओं की सूची को देखते हैं, तो यह वहां अभी भी कनेक्शन दिखाएगा। मैं मानता हूं कि आपको टीसीपी कनेक्शन के साथ इस तरह से खिलवाड़ नहीं करना चाहिए, और कनेक्शन को ठीक से डिस्कनेक्ट करने का एक तरीका होना चाहिए। लेकिन मामला वह नहीं है। इसलिए, यदि आप वास्तव में सर्वर से डिस्कनेक्ट करना चाहते हैं, तो आपके पास ऐसा कुछ करने के लिए होना चाहिए। नल को कनेक्शन सेट करना कनेक्शन विरोधाभासी को डिस्कनेक्ट नहीं करता है जो डॉक्स का कहना है।
जादहर्न

: मैं इस explaination पाया है stackoverflow.com/a/18277327/1315873
Fil

7

मैंने "$ कॉन = नल;" के बजाय अधिक स्व-दस्तावेजी निर्देश रखने के लिए एक व्युत्पन्न वर्ग बनाया।

class CMyPDO extends PDO {
    public function __construct($dsn, $username = null, $password = null, array $options = null) {
        parent::__construct($dsn, $username, $password, $options);
    }

    static function getNewConnection() {
        $conn=null;
        try {
            $conn = new CMyPDO("mysql:host=$host;dbname=$dbname",$user,$pass);
        }
        catch (PDOException $exc) {
            echo $exc->getMessage();
        }
        return $conn;
    }

    static function closeConnection(&$conn) {
        $conn=null;
    }
}

तो मैं अपने कोड के बीच कॉल कर सकते हैं:

$conn=CMyPDO::getNewConnection();
// my code
CMyPDO::closeConnection($conn);

1
आप CMyPDO :: __ निर्माण () विधि को निजी बना सकते हैं और वहां सिंगलटन पैटर्न का उपयोग कर सकते हैं ..
आदित्य हजारे

हाँ, यह कब्ज़ेदार है। यदि आप एक बार में एक से अधिक डेटाबेस का उपयोग करते हैं, तो आपको दूसरी विधि द्वारा कनेक्शन की जानकारी भी देनी होगी। अंतर न्यूनतम है, बस आपके पास इंस्टेंस विधियों को कॉल करने के लिए बहुत कम निर्देश हैं।
Fil

@ आदित्यहजारे आप एक उपवर्ग में एक
सुपरक्लास

@nickdnk, आप सही हैं। मेरा मतलब था कि एक स्टैंडअलोन वर्ग CMyPDO (इसे पीडीओ का विस्तार किए बिना) बनाना और फिर CMyPDO (नए PDO ($ dsn, $ dbuser, $ bbpass);) वर्ग के निजी निर्माणकर्ता के अंदर डेटाबेस का एक उदाहरण बनाना; उदाहरण पूरे एप्लिकेशन (सिंगलटन डिज़ाइन पैटर्न) में उपलब्ध है।
आदित्य हजारे

1
@ फ़िल लेकिन कोड "बाहर" closeConnectionको यह पता नहीं होना चाहिए कि उसे ऑब्जेक्ट को असाइन करने के बजाय चर के संदर्भ को कॉपी करने की आवश्यकता है। दूसरे शब्दों में, एक करीबी पीडीओ फ़ंक्शन को कोड करने का आपका तरीका खराब दुष्प्रभाव है, जिससे यह अविश्वसनीय हो जाता है। ऐसा करने का एकमात्र तरीका यह देखना होगा closeConnectionकि कोड में पीडीओ ऑब्जेक्ट के कितने संदर्भ मौजूद हैं, और 1 से अधिक मौजूद होने पर फेंक दें।
एक्सनोस

-1
<?php if(!class_exists('PDO2')) {
    class PDO2 {
        private static $_instance;
        public static function getInstance() {
            if (!isset(self::$_instance)) {
                try {
                    self::$_instance = new PDO(
                        'mysql:host=***;dbname=***',
                        '***',
                        '***',
                        array(
                            PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_general_ci",
                            PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION
                        )
                    );
                } catch (PDOException $e) {
                    throw new PDOException($e->getMessage(), (int) $e->getCode());
                }
            }
            return self::$_instance;
        }
        public static function closeInstance() {
            return self::$_instance = null;
        }
    }
}
$req = PDO2::getInstance()->prepare('SELECT * FROM table');
$req->execute();
$count = $req->rowCount();
$results = $req->fetchAll(PDO::FETCH_ASSOC);
$req->closeCursor();
// Do other requests maybe
// And close connection
PDO2::closeInstance();
// print output

पूर्ण उदाहरण, कस्टम वर्ग PDO2 के साथ।


1
कृपया या तो अपने कोड से ट्राई कैच को हटा दें या यहां दिखाए गए अनुसार नया थ्रो डालें । अभी आपका कोड सामान्य रूप से अपवाद और त्रुटि रिपोर्टिंग दोनों का दुरुपयोग करता है
आपका कॉमन सेंस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.