Удаление тысяч cron-задач
Я обнаружил, что в моей базе данных WordPress накопилось 29 000 cron-задач от деактивированных и удаленных плагинов. Я пробовал несколько плагинов-оптимизаторов, но из-за огромного количества cron-задач их невозможно удалить с помощью плагинов.
Я также пробовал следующий код в functions.php, но безуспешно:
add_action("init", "clear_crons_left");
function clear_crons_left() {
wp_clear_scheduled_hook("cron_name");
}
Есть ли SQL-команда, которую я могу использовать в phpMyAdmin для поиска cron-хуков и их удаления?

Спасибо, Privateer, за быстрый ответ и совет.
Я нашел решение до того, как увидел ваш ответ. Вот пошаговый метод удаления тысяч старых cron-задач, который может быть полезен кому-то еще.
Я вошел в phpMyAdmin. Выбрал свою базу данных, затем вкладку 'Search'. Ввел 'cron', выбрал 'All tables' и нажал 'Go'. Прокрутил список результатов поиска до таблицы wp_options. Нажал 'Browse'. В верхней части списка была запись option_name 'cron'. Нажал 'Edit' и подождал загрузки страницы. Кликнул на поле со списком cron-задач. Список был настолько длинным, что курсор реагировал только через 80 секунд. Затем использовал Ctrl-A на клавиатуре, чтобы выделить все, и нажал кнопку удаления. Удаление заняло около 2 минут (Chrome выдал таймаут, но Firefox справился).
Через пару минут cron-задачи для текущих активных плагинов снова заполнили список. Их стало 9 (вместо более 29 000!). Шесть лет дублирующихся задач от плохо написанных плагинов, некоторые из которых я устанавливал всего на день. А также сотни задач от распространенных плагинов, таких как Wordfence, BackupBuddy, Nextgen Gallery и AutoOptimizer, которые я давно удалил. Теперь мой сайт загружается как с турбонаддувом. Админка стала намного быстрее. Ошибки таймаута исчезли. Я потратил столько времени на оптимизацию сайта, пытаясь уменьшить время загрузки. Даже сменил хостинг и перешел на более дорогие тарифы. Ничто не ускорило сайт так, как удаление устаревших cron-задач. Время загрузки на мобильных устройствах сократилось с 20 до 6 секунд, на компьютерах — с 12 до 4 секунд.
Во время поиска решения я нашел очень мало информации о влиянии cron-задач на производительность сайта. Многие утверждали, что разница невелика, и для небольшого количества задач это действительно так. Но спустя годы работы WordPress-сайта, сколько из них забиты сотнями, если не тысячами старых задач от удаленных плагинов? Вместо того чтобы просить пользователей проверять лимит памяти PHP, разработчикам стоит сначала посоветовать проверить количество cron-задач в wp_options при решении проблем с фатальными ошибками памяти. Вы можете быть удивлены или даже шокированы тем, что обнаружите! :-)

У меня была такая же проблема. Я не знаю точное количество cron-заданий, но они занимали около 15 Мб в базе данных. После удаления время загрузки админки сократилось с 5-7 до 0.3 секунд. Время загрузки фронтенда уменьшилось с 2 до 0.4 сек.

Чёрт возьми! Это решение нас спасло! В таблице было 35000 cron-заданий. Теперь сайт работает как турбо, как и было описано.

Очень полезная информация, так как я как раз собирался установить один из упомянутых плагинов для клиента. Теперь я знаю, на что обращать внимание, если производительность начнёт постепенно ухудшаться.

События крона WordPress также можно очистить из командной строки с помощью WP-CLI:
wp cron event list
wp cron event delete your_example_event
Подробнее в документации wp-cli.

Попробуйте выполнить:
SELECT * FROM `wp_options` WHERE option_name = 'cron'
Если найдете запись, можете попробовать:
- В SQL:
UPDATE wp_options SET option_value = '' WHERE option_name = 'cron'
- В WordPress:
update_option('cron', '');
Возможно, вам потребуется либо удалить опцию cron, либо установить значение в виде пустой сериализованной массива.
Использование update_option будет безопаснее, так как я не уверен, должно ли значение быть пустой сериализованной массивом или пустой строкой. Вы можете проверить в wp-includes/options.php... но использование update_option обработает это правильно без необходимости беспокоиться о базе данных.

Ещё более простое решение — вызвать delete_option( 'cron' );
один раз в каком-нибудь плагине. Все автоматически добавленные задачи cron будут добавлены снова при следующем посещении/запросе вашего сайта.
В качестве однократного (mu) плагина, который запускается только при его активации:
<?php
/** Plugin Name: Clean Cron */
register_activation_hook( __FILE__, function()
{
delete_option( 'cron' );
} );

Спасибо, kaiser! Для тех, кому неудобно создавать/редактировать плагины (это просто!), вы можете использовать то, что отметил kaiser, в вашем файле functions.php. Просто добавьте его, сохраните, загрузите ваш сайт, затем удалите и снова сохраните.

А как насчёт cron-задач, которые были созданы при активации плагина? Эти cron-задачи не будут воссозданы, пока вы не деактивируете и не активируете плагин снова.

Ну, это невозможно по умолчанию, ни с этим, ни с другими вопросами. Что вам нужно сделать — это либо деактивировать и активировать эти плагины снова (~3 минуты работы), либо — если вы ищете автоматизированное решение — найти функции в этих плагинах и запустить их из вашего плагина.

Если нужно удалить конкретный cron по имени (например, 'CRON_NAME'), мне помогло это решение:
$crons = _get_cron_array();
//echo "Найдено всего ".count($crons)."<br />";
//Оставляем только те, которые не совпадают с именем крона
$updated = array_filter($crons, function($v){return !array_key_exists("CRON_NAME",$v);});
//echo "Сокращено до ".count($updated)."<br />";
_set_cron_array($updated);

У меня был год, полный отложенных cron-задач, около 5 Мб данных для этой единственной записи в базе данных. Удалил cron-задачи из базы данных. Отключил cron-задачи в wp-config.php.
Настроил ручной cron-задачу в cpanel. Теперь мой сайт буквально летает. Я уже обновлял серверы, покупал больше CPU/RAM, но все это было пустой тратой денег и времени.
Чтобы удалить все отложенные cron-задачи, выполните этот запрос в phpmyadmin>Выполнить SQL-запрос:
UPDATE wp_options SET option_value = '' WHERE option_name = 'cron'
Большое спасибо Pádraig Ó Beirn.

Я столкнулся с похожей проблемой, когда из-за моей собственной ошибки в коде на сайт было добавлено тысячи копий одного определенного крона. Функция wp_clear_scheduled_hook зависала и не выполнялась. Я обошел это с помощью скрипта, который удаляет все экземпляры крона из массива, а затем добавляет отфильтрованный массив как новую опцию крона в таблицу options. Смотрите ниже.
Таким образом, я избежал удаления желаемых кронов, ранее добавленных на сайт.
Это можно модифицировать как функцию, принимающую массив названий для удаления или массив названий для сохранения.
$crons = _get_cron_array();
$hook = 'tj_flush_w3tc_cache';
foreach ( $crons as $timestamp => $cron ) {
if ( isset( $cron[ $hook ] ) ) {
unset($cron[$hook]);
}
if(!empty($cron))
$newcron[$timestamp] = $cron;
}
update_option('cron',$newcron);

У меня есть очень простой способ удалить все события крона. Перед этим необходимо ОТКЛЮЧИТЬ WP Cron в файле wp-config. Затем установите плагин WP Control. После этого перейдите в меню Инструменты > События Cron > Выберите все > Удалить все. Попробуйте этот способ. Спасибо.

Если вы очистите задачи cron таким образом и используете UpdraftPlus, вам нужно будет повторно сохранить настройки, чтобы восстановить задачи cron. Пока вы этого не сделаете, автоматические резервные копии не будут создаваться (но ручные резервные копии будут работать).
Настройки останутся прежними, и вам не нужно ничего редактировать. Просто перейдите в [верхнее меню UpdraftPlus]→Настройки, прокрутите вниз и нажмите «Сохранить изменения».

Я попал сюда из-за огромного количества задач sm_ping
в кроне в таблице wp_options
. Если у вас та же проблема, вы можете попробовать следующее:
Добавьте этот код в functions.php (дочерней темы), если у вас нет доступа к phpmyadmin, особенно если ваш сайт перегружен задачами ping в кроне (sm_ping):
if (isset($_GET['doing_wp_cron'])) {
remove_action('do_pings', 'do_all_pings');
wp_clear_scheduled_hook('do_pings');
}
