Я отправляю это, если кто-то ищет такое же решение, потому что я просто потратил два дня на эту ерунду.
У меня есть задание cron, которое обновляет базу данных, используя очень большой файл один раз в день, используя следующий код:
if (($handle = fopen(dirname(__FILE__) . '/uncompressed', "r")) !== FALSE) { while (($data = fgets($handle)) !== FALSE) { $thisline = json_decode($data, true); $this->regen($thisline); } fclose($handle); }
Это находится в контроллере Codeigniter, который используется только для заданий cron. Функция $ this-> regen проходит через кучу разных проверок и сохраняет правильную информацию из строки в базе данных. Сам файл содержит более 300 МБ JSON, разделенных символами новой строки.
Проблема: он обработает только около 20 000 строк до того, как все закончится.
Я потратил несколько часов на то, чтобы устранить это и не получил ничего очевидного. Я использую fgets, у меня есть $ query-> free_result () в нужных местах. Это не помогло. Итак, я начал проверять цикл из примерно 100 строк и смотрел вывод memory_get_usage (). Я, наконец, сузил его до класса Codeigniter Active Record – каждый вызов класса заставлял использование памяти увеличиваться на крошечную сумму.
Затем я нашел эту тему на Ellislabs, и я получил ответ. CI Active Record сохраняет запросы, так что если вы хотите, вы можете построить запрос в нескольких функциях. (Я даже не собираюсь вдаваться в то, насколько глупым это было включено по умолчанию.)
Перейдите в /config/database.php и добавьте
$db['default']['save_queries'] = FALSE;
до конца файла. Затем убедитесь, что вы создаете и выполняете запросы с помощью Active Record в одной функции. Если вам нужно отключить его только для одного случая, используйте
$this->db->save_queries = FALSE;
в конструкторе или там, где вам нужно его поместить.