2014-10-10 3 views
0

Чтобы получить скрипт, работающий с PHP 5.5, я фактически перехожу от mysql-расширения к 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 устанавливается равным 256 МБ.

+2

PDO не вызывает переполнение памяти, ваше использование fetchAll() вызывает переполнение памяти , Выбирайте свои строки по одному за раз –

+1

Весь ваш набор результатов буферизуется в память, когда вы вызываете 'fetchAll()'. Хитрость заключается в том, чтобы позволить MySQL выполнять работу там, где это возможно, уменьшая набор результатов с помощью вашего запроса - то есть 'SELECT field1, field2' вместо' SELECT * ', особенно если таблица имеет большое количество столбцов. Если вы опускаете 50000 строк ... ну, вы можете увидеть эту проблему здесь, конечно? Кроме того, почему вы вызываете PHP_EOL 12 раз за одну короткую функцию? Вы вызываете это через командную строку или экспортируете ее? – iamgory

+0

Мне нужны все поля таблицы, потому что скрипт должен архивировать всю базу данных. Поэтому ваше решение с именованием полей ничего не изменит. –

ответ

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; 
} 
Смежные вопросы