2009-02-12 8 views
8

disconnect invalidates 1 active statement handle (either destroy statement handles or call finish on them before disconnecting)अपाचे शिकायत क्यों करता है कि मेरा mod_perl प्रोग्राम "डिस्कनेक्ट 1 सक्रिय कथन संभाल को अमान्य करता है"?

निम्नलिखित कोड जो पकड़ लेता है MySQL से डेटा सफलतापूर्वक क्रियान्वित हो जाता है, लेकिन अपाचे अपने त्रुटि लॉग में उपरोक्त संदेश उत्पन्न करने के लिए कारण होगा:

my $driver = "mysql"; 
my $server = "localhost:3306"; 
my $database = "test"; 
my $url  = "DBI:$driver:$database:$server"; 
my $user  = "apache"; 
my $password = ""; 

#Connect to database 
my $db_handle = DBI->connect($url, $user, $password) 
    or die $DBI::errstr; 

#SQL query to execute 
my $sql = "SELECT * FROM tests WHERE id=?"; 

#Prepare SQL query 
my $statement = $db_handle->prepare($sql) 
     or die "Couldn't prepare query '$sql': $DBI::errstr\n"; 

#Execute SQL Query 
$statement->execute($idFromSomewhere) 
    or die "Couldn't execute query '$sql': $DBI::errstr\n"; 

#Get query results as hash 
my $results = $statement->fetchall_hashref('id'); 

$db_handle->disconnect(); 
  • वहाँ किसी भी गंभीर परिणाम की अनदेखी करके करेंगे कहा त्रुटि/चेतावनी? कोड किसी भी बीमार प्रभाव के बिना के लिए चल रहा है।

  • क्या कोड कोड के साथ कुछ गलत है या यह सिर्फ एक हानिकारक चेतावनी है?

संपादित

कोड मोड-पर्ल के माध्यम से क्रियान्वित किया जाता है।

+0

हे ब्रायन, शीर्षक संपादित करने के लिए धन्यवाद। मैंने पहले आपकी सभी किताबें पढ़ीं। – GeneQ

उत्तर

12

आपको $db_handle->disconnnect(); से पहले $statement->finish(); पर कॉल करना चाहिए।

आम तौर पर आपको finish पर कॉल करने की आवश्यकता नहीं है, जब तक कि आप सभी पंक्तियां नहीं प्राप्त कर रहे हों। यदि आपको fetchrow_array का उपयोग करके लूप में सभी परिणाम मिलते हैं, तो आप अंत तक खत्म नहीं करते हैं जब तक आप लूप को निरस्त नहीं करते।

मुझे यकीन नहीं है कि MySQL ड्राइवर fetchall_hashref के बाद कथन को समाप्त क्यों नहीं कर रहा है। मैनुअल पता चलता है कि आपकी क्वेरी एक त्रुटि के कारण निरस्त किया जा सकता है:

If an error occurs, fetchall_hashref returns the data fetched thus far, which may be none. You should check $sth->err afterwards (or use the RaiseError attribute) to discover if the data is complete or was truncated due to an error.

+0

धन्यवाद, यह चाल है। हालांकि O'Reilly डीबीआई पुस्तक और पर्ल दस्तावेज पढ़ना अन्यथा सुझाव देते हैं। 16 मिनट में हल! Stackoverflow जाओ! – GeneQ

+0

मेरे प्रश्न पॉल के "क्यों" भाग का जवाब देने के लिए धन्यवाद। ;-) आप अपने 15k कर्म के लायक हैं। – GeneQ

+0

डेटा ठीक है। यह एक सप्ताह के लिए लगातार 1K लोगों द्वारा बढ़ा दिया गया है। हां, प्रलेखन ऐसा कहता है। वैसे भी, यह सिर्फ MySQL ड्राइवर हो सकता है। कॉलिंग के बाद() चेतावनी प्रकट हो रही है। मैं डीबीआई और MYSQL के नवीनतम निर्माण में अपग्रेड करने जा रहा हूं और देखें कि क्या होता है। – GeneQ

3

इस संभाल अभी भी सक्रिय किया जा रहा है के कारण होता है। आम तौर पर इसे खुद को बंद करना चाहिए, लेकिन ऐसा लगता है कि आप इससे सभी डेटा प्राप्त नहीं कर रहे हैं। DBI पर perldoc से:

When all the data has been fetched from a SELECT statement, the driver should automatically call finish for you. So you should not normally need to call it explicitly except when you know that you've not fetched all the data from a statement handle. The most common example is when you only want to fetch one row, but in that case the selectrow_* methods are usually better anyway. Adding calls to finish after each fetch loop is a common mistake, don't do it, it can mask genuine problems like uncaught fetch errors.

+0

धन्यवाद। मैंने इसे भी पढ़ा और सोचा कि यह अनिवार्य नहीं है। – GeneQ

+0

लेकिन वह fetchall_hashref को कॉल कर रहा है - यह सभी परिणाम प्राप्त करने वाला है! –

+0

अच्छा बिंदु, उसे पकड़ नहीं लिया। निश्चित रूप से जानने का एकमात्र तरीका मुझे लगता है कि fetchall पर त्रुटियों की जांच है। – wds

0

हालांकि शायद यही कारण है नहीं तो आप इस चेतावनी मिला (जो क्या manual दावों यह है कि), मैं थोड़ा अलग परिस्थितियों में एक ही चेतावनी का अनुभव है और यह सुझाव देना चाहता था अपना खुद का प्रश्न खोलने के बजाय यहां।

यदि आप कुछ पंक्तियां लाने के लिए कोई प्रश्न पूछते हैं तो आप खुद को इस परिदृश्य में पा सकते हैं - लेकिन केवल यह जानने के इरादे के लिए कि पंक्तियां हैं या नहीं। मेरे परिस्थिति में, यदि कोई मिलान मिलता है और अन्यथा सम्मिलित होता है तो हम पंक्तियों को अपडेट करेंगे।

क्योंकि पाए गए पंक्तियों के साथ कुछ भी नहीं किया जाता है, मेरा मानना ​​है कि यह एक परिदृश्य है जहां चेतावनी के नेतृत्व का पालन करना उचित है। इसलिए, मैं डिस्कनेक्ट करने से पहले अपने चयन हैंडलर पर finish() पर कॉल करता हूं।

अस्वीकरण: डीबीआई के लिए नया होने के नाते, संभावित रूप से एक बेहतर दृष्टिकोण है। the documentation को छोड़कर मैंने ->do() का उपयोग किया होगा, यह इंगित करता है कि बार-बार निष्पादित होने पर उपयोग किया जाना चाहिए - कुछ कारणों से SELECT कथन भी निराश थे!

$selectHandler = $dbh->prepare($queryString) or die "Cannot prepare: ".$dbh->errstr; 
#Loop through a list of keys to check existence { 
    $selectHandler.execute($uniqueID); 
    $found = 0; 
    $found = $selectHandler->fetch(); 
    if (!$found) { 
     # Do an insert of $uniqueID 
    } else { 
     # Do an update of $uniqueID 
    } 
#} 
# Having not done anything with the selectHandler's result (when rows were 
# found) close it now that the loop is complete 
$selectHandler->finish(); # we don't need you any more select handler! 
$dbh->disconnect or warn "Disconnection error: $DBI::errstr\n"; 

आशा इस किसी और और मेरे दृष्टिकोण को सही करने के अगर मैं किसी को भी गुमराह कर रहा हूँ के लिए स्वतंत्र महसूस में मदद करता है:

यहाँ कुछ पर्ल दिखा क्या मैं पर उतरा स्यूडोकोड है।

संबंधित मुद्दे

 संबंधित मुद्दे