Как я могу освободить память, используемую для обновления мета-сообщений?


Я заметил, что каждый вызов 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 или что-то еще кэширует что-то, чего я не хочу, или что где-то произошла утечка памяти, но я не могу этого понять.

Author: Pikamander2, 2019-06-11

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 похоже, что это не проблема, по крайней мере, сама по себе.

 2
Author: Pikamander2, 2019-06-11 09:34:45

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

Каждый раз, когда вы делаете что-либо, требующее большого количества операций с БД, вы рискуете столкнуться с нехваткой памяти, пропускной способностью сервера БД или нехваткой времени. Это может быть очень сложно, так как что-то, что может работать на одном сервере, выйдет из строя на другом.

Правильный способ выполнить любую операцию, требующую обработки множества записей, - разделить ее на обработка только (например) 100 из них за раз и использование процесса на основе AJAX для контроля хода операции до тех пор, пока все данные не будут обработаны.

Наверняка со временем PHP и MySQL стали быстрее, а аппаратное обеспечение стало сильнее, поэтому вам может сойти с рук использование наивного подхода "грубой силы" в вашем коде, но вы идете по краю, особенно если ваш код не просто "одноразовый" и его нужно будет использовать снова.

 1
Author: Mark Kaplun, 2019-06-11 10:44:20