2011-12-31 6 views
12

मैंने PHP में कुछ कोड लिखा है जो .edu डोमेन से HTML सामग्री देता है। एक संक्षिप्त परिचय यहाँ दिया जाता है: Errors regarding Web Crawler in PHPहल करना "MySQL सर्वर चला गया है" त्रुटियां

क्रॉलर ठीक काम करता है जब लिंक को क्रॉल करने की संख्या कम कर रहे हैं (कुछ लगभग 40 यूआरएल) लेकिन मैं हो रही है इस संख्या के बाद "MySQL सर्वर दूर चला गया है" त्रुटि।

मैं एचटीएमएल सामग्री को MySQL तालिकाओं में लंबे समय तक संग्रहीत कर रहा हूं और मुझे नहीं मिल रहा है कि त्रुटि कम से कम 40-50 प्रविष्टियों के बाद क्यों आती है।

इस संबंध में कोई भी मदद अत्यधिक सराहना की है।

कृपया ध्यान दें कि मैंने पहले से ही प्रतीक्षा_टाउटआउट और max_allowed_packet को मेरे प्रश्नों और PHP कोड को समायोजित करने के लिए बदल दिया है और अब मुझे नहीं पता कि क्या करना है। कृपया इस बारे में मेरी मदद करें।

उत्तर

10

आप एक प्रश्न से पहले "पिंग" mysql सर्वर द्वारा इस समस्या को संभालने के लिए इच्छुक हो सकती है। यह विचार अच्छा नहीं है। क्यों के बारे में अधिक के लिए, यह जाँच अतः पोस्ट: Should I ping mysql server before each query?

मुद्दे को सुलझाने का सबसे अच्छा तरीका try/catch ब्लॉक के अंदर प्रश्नों लपेटकर और किसी भी डेटाबेस अपवादों को पकड़ने ताकि आप उन्हें उचित रूप से संभाल कर सकते हैं कर रहा है। यह लंबे समय तक चलने और/या डेमॉन प्रकार की स्क्रिप्ट में विशेष रूप से महत्वपूर्ण है।

class DbPool { 

    private $connections = array(); 

    function addConnection($id, $dsn) { 
     $this->connections[$id] = array(
      'dsn' => $dsn, 
      'conn' => null 
     ); 
    } 

    function getConnection($id) { 
     if (!isset($this->connections[$id])) { 
      throw new Exception('Invalid DB connection requested'); 
     } elseif (isset($this->connections[$id]['conn'])) { 
      return $this->connections[$id]['conn']; 
     } else { 
      try { 
       // for mysql you need to supply user/pass as well 
       $conn = new PDO($dsn); 

       // Tell PDO to throw an exception on error 
       // (like "MySQL server has gone away") 
       $conn->setAttribute(
        PDO::ATTR_ERRMODE, 
        PDO::ERRMODE_EXCEPTION 
       ); 
       $this->connections[$id]['conn'] = $conn; 

       return $conn; 
      } catch (PDOException $e) { 
       return false; 
      } 
     } 
    } 

    function close($id) { 
     if (!isset($this->connections[$id])) { 
      throw new Exception('Invalid DB connection requested'); 
     } 
     $this->connections[$id]['conn'] = null; 
    } 


} 


class Crawler { 

    private $dbPool; 

    function __construct(DbPool $dbPool) { 
     $this->dbPool = $dbPool; 
    } 

    function crawl() { 
     // craw and store data in $crawledData variable 
     $this->save($crawledData); 
    } 

    function saveData($crawledData) { 
     if (!$conn = $this->dbPool->getConnection('write_conn') { 
      // doh! couldn't retrieve DB connection ... handle it 
     } else { 
      try { 
       // perform query on the $conn database connection 
      } catch (Exception $e) { 
       $msg = $e->getMessage(); 
       if (strstr($msg, 'MySQL server has gone away') { 
        $this->dbPool->close('write_conn'); 
        $this->saveData($val); 
       } else { 
        // some other error occurred 
       } 
      } 
     } 
    } 
} 
+0

क्या डीबीएक्सप्शन पहले से ही php में है ?? – Rafay

+2

नहीं, यह एक अपवाद वर्ग है जिसे आप स्वयं निर्दिष्ट करेंगे और 'saveData()' फ़ंक्शन के अंदर से फेंक देंगे। मैंने 'saveData' फ़ंक्शन को अपडेट किया है और इसे प्रतिबिंबित करने के लिए मेरे उत्तर में कस्टम डीबीएक्सप्शन क्लास जोड़ा है ... – rdlowrey

3

मेरे पास another answer है जो मुझे लगता है कि एक ही समस्या है, और इसके समान जवाब की आवश्यकता होगी। असल में, आप अपने डालने से पहले कनेक्शन का परीक्षण करने के लिए mysql_ping() फ़ंक्शन का उपयोग कर सकते हैं। MySQL 5.0.14 से पहले, mysql_ping() स्वचालित रूप से सर्वर को फिर से कनेक्ट कर देगा, लेकिन अब आपको अपना खुद का पुन: कनेक्ट तर्क बनाना होगा। इस के समान कुछ आप के लिए काम करना चाहिए:

function check_dbconn($connection) { 
    if (!mysql_ping($connection)) { 
     mysql_close($connection); 
     $connection = mysql_connect('server', 'username', 'password'); 
     mysql_select_db('db',$connection); 
    } 
    return $connection; 
} 

foreach($array as $value) { 
    $dbconn = check_dbconn($dbconn); 
    $sql="insert into collected values('".$value."')"; 
    $res=mysql_query($sql, $dbconn); 
    //then some extra code. 
} 
+1

Pinging क्यों, इस अतः पद की जाँच के बारे में अधिक के लिए इस मामले में एक अच्छी रणनीति नहीं है ...: [क्या मुझे प्रत्येक क्वेरी से पहले पिंग mysql सर्वर?] (Http: // stackoverflow।कॉम/प्रश्न/3103969/चाहिए-i-ping-mysql-server-before-each-query) – rdlowrey

0

आप एक ही DB कनेक्शन खोलने और यह पुन: उपयोग कर रहे हैं: तो, यहाँ एक "कनेक्शन प्रबंधक" का उपयोग कर डीबी कनेक्शन के लिए उपयोग को नियंत्रित करने के एक बहुत ही बुनियादी उदाहरण है? क्या यह संभव है कि यह एक साधारण टाइमआउट है? आप अपने प्रत्येक पढ़ने/लिखने के संचालन के लिए एक नया डीबी कनेक्शन खोलकर बेहतर सेवा कर सकते हैं (आईई संपर्क .edu, टेक्स्ट प्राप्त करें, खुले डीबी, टेक्स्ट लिखें, करीबी डीबी, दोहराना)।

इसके अलावा, आप संभाल कैसे उपयोग कर रहे हैं? क्या यह संभव है कि उसने एक त्रुटि मारा है और उस कारण से 'चले गए' हैं?

+0

क्या मुझे प्रत्येक क्वेरी के लिए एक नया कनेक्शन खोलना चाहिए और फिर उस क्वेरी को निष्पादित करने के बाद इसे बंद करना चाहिए ?? और सभी प्रश्नों के लिए प्रक्रिया दोहराएं ?? – Rafay

+4

रिकॉर्ड के लिए, प्रत्येक क्वेरी के लिए एक नया कनेक्शन खोलना बेहद अक्षम है ... – rdlowrey

+0

यह जोड़ना उचित है कि अगर डीबी पर थ्रेड मारा जाता है ('किल [थ्रेड आईडी 'के साथ) तो आपको" सर्वर है दूर चला गया "त्रुटि भी। –

0

खैर यह वही है मैं अब rdlowrey के सुझाव के आधार पर कर रहा हूँ और मुझे लगता है कि यह भी सही है।

public function url_db_html($sourceLink = NULL, $source) { 
    $source = mysql_real_escape_string($source); 

    $query = "INSERT INTO html (id, sourceLink, sourceCode) 
      VALUES (NULL,('$sourceLink') , ('$source'))"; 

    try { 
     if(mysql_query($query, $this->connection)==FALSE) { 
      $msg = mysql_errno($this->connection) . ": " . mysql_error($this->connection); 
      throw new DbException($msg); 
     }   
    } catch (DbException $e) { 
     echo "<br><br>Catched!!!<br><br>"; 
     if(strstr($e->getMessage(), 'MySQL server has gone away')) { 
      $this->connection = mysql_connect("localhost", "root", ""); 
      mysql_select_db("crawler1", $this->connection); 
     } 
    } 
} 

तो एक बार क्वेरी को निष्पादित करने में नाकाम रही है, स्क्रिप्ट इसे छोड़ जाएगा, लेकिन यकीन है कि कनेक्शन को पुन: स्थापित कर देगा।

हालांकि, मेरा वेब क्रॉलर क्रैश हो रहा है जब .jpg, .bmp, .pdf, आदि जैसी फ़ाइलें सामने आती हैं। क्या इन एक्सटेंशन वाले यूआरएल को छोड़ने का कोई तरीका है। मैं preg_match का उपयोग कर रहा हूं और मिलान करने के लिए पीडीएफ और डॉक्टर दिया है। फिर भी मैं चाहता हूं कि फ़ंक्शन को एमपी 3, पीडीएफ इत्यादि जैसे एक्सटेंशन वाले सभी लिंक छोड़ दें। क्या यह संभव है ??

+0

यदि आपका डीबी कनेक्शन बंद हो रहा है तो यह 2 में से 1 कारणों से होगा: 1) आपका कोड इसे बंद कर रहा है। 2) आपके सिस्टम में कुछ बड़ी समस्या है। मैंने कभी भी इस रीकनेक्ट रणनीति को कभी नहीं देखा है क्योंकि मैंने कभी ऐसी स्थिति नहीं देखी है जहां इसकी आवश्यकता होनी चाहिए। अपने कैच ब्लॉक में पुनः कनेक्ट करने के बजाय, अपवाद विवरण लॉगिंग करने और वहां से समस्या को डीबग करने का प्रयास करें। –

2

मुझे का सामना करना पड़ रहा था, Mysql connector 5.X का उपयोग करते समय "माइस्क्ल सर्वर दूर चला गया है" त्रुटि, अंतिम संस्करण में डीएल को बदलकर समस्या हल हो गई।