Как я могу освободить память, используемую для обновления мета-сообщений?
Я заметил, что каждый вызов update_post_meta приводит к небольшому увеличению использования моей памяти.
Обычно увеличение достаточно мало, чтобы не иметь значения. Но я пишу функцию импорта CSV, которая вызывает ее более 10 000 раз, что в конечном итоге приводит к ошибке нехватки памяти.
Вот минимальный пример кода:
function update_business($myData)
{
error_log("Used memory 1: " . memory_get_usage(false));
error_log("Allocated memory 1: " . memory_get_usage(true));
update_post_meta('13663', 'business_id', $myData);
error_log("Used memory 2: " . memory_get_usage(false));
error_log("Allocated memory 2: " . memory_get_usage(true));
}
Это приводит к:
...
Used memory 1: 17995848
Used memory 2: 17996992
Used memory 1: 17996992
Used memory 2: 18027720
Used memory 1: 18027720
Used memory 2: 18058448
Used memory 1: 18058448
Used memory 2: 18089176
Used memory 1: 18089176
Used memory 2: 18119904
...
Без оператора update_post_meta
использование памяти остается неизменным на протяжении всего цикл (как и ожидалось).
Но с помощью оператора update_post_meta
использование памяти становится все больше и больше и никогда не освобождается.
Я перепробовал множество различных методов очистки памяти, в том числе:
- wpdb::флеш
- не установлено
- gc_коллект_циклов
- wp_cache_flush
- wp_suspend_cache_addition(значение true) wp_suspend_cache_addition(значение true)
Но, похоже, ничего не работает.
Я просмотрел тонны результатов поиска, и хотя у многих людей были на эту проблему существует не так много ответов, кроме "увеличить лимит памяти" или "сделать это по-другому", ни один из которых не кажется лучшим решением.
Наверняка есть какой-то способ освободить память? Я предполагаю, что либо WordPress, PHP, MySQL или что-то еще кэширует что-то, чего я не хочу, или что где-то произошла утечка памяти, но я не могу этого понять.
2 answers
Оказывается, это произошло из-за монитора запросов, плагина, который записывает информацию о каждом запросе. Каждый раз при запуске update_post_meta монитор запросов сохранял некоторые данные о запросе, которые в конечном итоге составляли больше, чем мог обработать сервер.
Запуск моего примера кода в теме по умолчанию, такой как Twenty Nineteen, без других включенных плагинов приводит к ожидаемому поведению:
...
Used memory 1: 5480528
Used memory 2: 5480528
Used memory 1: 5480528
Used memory 2: 5480528
...
Поэтому, если вы столкнулись с подобной проблемой, попробуйте отключить все свои плагины и переключение на тему по умолчанию, чтобы помочь сузить проблему.
update_post_meta
похоже, что это не проблема, по крайней мере, сама по себе.
Хотя хорошо, что вы обнаружили конкретную проблему в своей настройке, общий ответ заключается в том, что вы делаете это неправильно.
Каждый раз, когда вы делаете что-либо, требующее большого количества операций с БД, вы рискуете столкнуться с нехваткой памяти, пропускной способностью сервера БД или нехваткой времени. Это может быть очень сложно, так как что-то, что может работать на одном сервере, выйдет из строя на другом.
Правильный способ выполнить любую операцию, требующую обработки множества записей, - разделить ее на обработка только (например) 100 из них за раз и использование процесса на основе AJAX для контроля хода операции до тех пор, пока все данные не будут обработаны.
Наверняка со временем PHP и MySQL стали быстрее, а аппаратное обеспечение стало сильнее, поэтому вам может сойти с рук использование наивного подхода "грубой силы" в вашем коде, но вы идете по краю, особенно если ваш код не просто "одноразовый" и его нужно будет использовать снова.