PHP / Mysql «Неустранимая ошибка: допустимый объем памяти исчерпан ..» при попытке вставить большой объем данных в чанки - PullRequest
0 голосов
/ 05 ноября 2019

Я перевожу старый проект PHP в новое приложение Laravel. Есть таблица с несколькими миллионами записей user_category_views, которую я планировал перенести порциями. Я получаю старые записи с mysqli и вставляю с Laravel DB::Statement. По какой-то причине после примерно миллиона записей этот код падает с исключением:

Неустранимая ошибка: допустимый объем памяти 268435456 байт исчерпан (попытка выделить 73728 байт)

Что здесь переполняет память? Может быть $result->free() не работает так, как я думаю?

        $count = 2000000; // actual number will be received from count(*) stmt
        $vendors = [561 => '618', 784 => '512' /* and so on */ ];
        $step = 5000;
        for( $i=0; $i<=$count; $i+=$step ){

            $q = "SELECT * FROM `user_category_views` LIMIT $i, $step;";

            if ($result = $this->mysqli->query($q)) {

                $stmt = "INSERT INTO vendor_views (`vendor_id`, `counter`, `created_at`) VALUES";

                /* fetch associative array */
                while ($row = $result->fetch_assoc()) {

                    $vendor_id = null;

                    $id = $row['user_category_id'];

                    // Here I'm trying to prevent Laravel 
                    // from throwing the exception if the entry 
                    // is not found in $vendors array. 
                    // This habit I've gained from js coding  
                    try{
                       $vendor_id = $vendors[$id];
                    } catch (Exception $e) {
                       continue;
                    }

                    if(empty($vendor_id)) continue;

                    $counter = $row['counter'];
                    $created = $row['created'] ;

                    $stmt .= " ($vendor_id, $counter, '{$created}'),";

                }

                $result->free();

                DB::statement( trim($stmt, ",") );

                $stmt = null;

            }
        }

Ответы [ 2 ]

0 голосов
/ 05 ноября 2019

Спасибо Найджелу Рену, который указал, что я неправильно использую конструкцию try / catch

Так что вместо

    .....
    try{
        $vendor_id = $vendors[$id];
    } catch (Exception $e) {
        continue;
    }
    ....

я использую сейчас

$vendor_id = $vendors[$id]??null;

И больше нет проблемы утечки памяти. Не знаю, почему, хотя, но теперь это работает

0 голосов
/ 05 ноября 2019

Ваша проблема в том, что ваша память ограничена. Попробуйте установить в верхней части вашего PHP-файла:

ini_set('memory_limit', '-1');

Чтобы увеличить ограничение памяти для PHP.

Если вышеуказанное решение не работает. Может быть, ваша память переполнена. пожалуйста, проверь это. Вы также можете уменьшить свой шаг как $ step = 5000;до $ step = 1000;Я думаю, что это лучше

Надеюсь, это поможет. Спасибо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...