2014-10-10 103 views
0

爲了使腳本與PHP 5.5一起工作,我實際上從mysql-extension改爲PDO。使用mysql擴展它可以正常工作,但是使用PDO會導致內存溢出。PDO導致內存溢出

這裏是我使用的功能:

protected function getData($table) { 
    global $db; 
    $insert = ''; 
    $stmt = $db->query("-- " . __LINE__ . __FILE__ . " 
    SELECT * 
    FROM " . $table 
); 
    if ($result = $stmt->fetchAll()) { 
    $insert_into = "INSERT INTO `" . $table . "` VALUES ". PHP_EOL; 
    $insert = "/*!40000 ALTER TABLE `" . $table . "` DISABLE KEYS */;" . PHP_EOL; 
    $insert .= $insert_into; 
    $countRow = 0; 
    $split_tmp = ''; 
    foreach ($result as $row) { 
     $insert_tmp = "("; 
     foreach ($row as $data) { 
     if (!isset($data)) { 
      $insert_tmp .= 'NULL,'; 
     } else if ($data != '') { 
      $insert_tmp .= "'" . addslashes($data) . "',"; 
     } else { 
      $insert_tmp .= "'',"; 
     } 
     } 
     $insert_tmp = rtrim($insert_tmp, ',') . '),' . PHP_EOL; 
     $insert .= $insert_tmp; 
     if ($this->querySplit) { 
     $split_tmp .= $insert_tmp; 
     if ($countRow > $this->maxRow && strlen($split_tmp) > $this->maxLength) { 
      $countRow  = 0; 
      $split_tmp = ''; 
      $insert = rtrim($insert, PHP_EOL . ',') . ';' . PHP_EOL; 
      $insert .= "/*!40000 ALTER TABLE `" . $table . "` ENABLE KEYS */;" . PHP_EOL . PHP_EOL; 
      $insert .= "/*!40000 ALTER TABLE `" . $table . "` DISABLE KEYS */;" . PHP_EOL; 
      $insert .= $insert_into; 
     } 
     } 
     $countRow ++; 
    } 
    $insert = rtrim($insert, PHP_EOL . ',') . ';' . PHP_EOL; 
    $insert .= "/*!40000 ALTER TABLE `" . $table . "` ENABLE KEYS */;" . PHP_EOL. PHP_EOL; 
    } 
    return $insert; 
} 

即使切換到

$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); 

沒有幫助。

memory_limit設置爲256MB。

+2

PDO不會造成內存溢出以下調整,您使用fetchall()的使用會導致內存溢出。一次取一行 – 2014-10-10 10:26:41

+1

當您調用'fetchAll()'時,您的整個結果集將被緩衝到內存中。訣竅是讓MySQL儘可能減少結果集的數量,例如'SELECT field1,field2'而不是'SELECT *',特別是如果表中有大量的列。如果你拉下50000行......那麼你肯定能看到這個問題嗎? 此外,你爲什麼要在一個短的函數中調用PHP_EOL 12次?你是通過命令行調用它還是導出它? – iamgory 2014-10-10 11:29:49

+0

我需要所有的表字段,因爲腳本要備份整個數據庫。所以你的命名字段的解決方案不會改變任何東西。 – 2014-10-10 13:56:04

回答

0

使用fetchAll是一個非常糟糕的主意用大量的數據的時候,做使用fetch()

protected function getData($table) { 
    global $db; 
    $insert = ''; 
    $stmt = $db->query("-- " . __LINE__ . __FILE__ . " 
    SELECT * 
    FROM " . $table 
); 
    if ($result = $stmt->rowCount() > 0) { 
    $insert_into = "INSERT INTO `" . $table . "` VALUES ". PHP_EOL; 
    $insert = "/*!40000 ALTER TABLE `" . $table . "` DISABLE KEYS */;" . PHP_EOL; 
    $insert .= $insert_into; 
    $countRow = 0; 
    $split_tmp = ''; 
    while($row = $stmt->fetch()) { 
     $insert_tmp = "("; 
     foreach ($row as $data) { 
     if (!isset($data)) { 
      $insert_tmp .= 'NULL,'; 
     } else if ($data != '') { 
      $insert_tmp .= "'" . addslashes($data) . "',"; 
     } else { 
      $insert_tmp .= "'',"; 
     } 
     } 
     $insert_tmp = rtrim($insert_tmp, ',') . '),' . PHP_EOL; 
     $insert .= $insert_tmp; 
     if ($this->querySplit) { 
     $split_tmp .= $insert_tmp; 
     if ($countRow > $this->maxRow && strlen($split_tmp) > $this->maxLength) { 
      $countRow  = 0; 
      $split_tmp = ''; 
      $insert = rtrim($insert, PHP_EOL . ',') . ';' . PHP_EOL; 
      $insert .= "/*!40000 ALTER TABLE `" . $table . "` ENABLE KEYS */;" . PHP_EOL . PHP_EOL; 
      $insert .= "/*!40000 ALTER TABLE `" . $table . "` DISABLE KEYS */;" . PHP_EOL; 
      $insert .= $insert_into; 
     } 
     } 
     $countRow ++; 
    } 
    $insert = rtrim($insert, PHP_EOL . ',') . ';' . PHP_EOL; 
    $insert .= "/*!40000 ALTER TABLE `" . $table . "` ENABLE KEYS */;" . PHP_EOL. PHP_EOL; 
    } 
    return $insert; 
}