Собирается ли временный мусор?

61

Этот вопрос заставил меня задуматься, что временные RSS-каналы в wp_options не удаляются автоматически?

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

Что если переходный период истек, но после этого никогда не запрашивается? Из описания в Кодексе я подумал, что подразумевается какая-то сборка мусора. Теперь я не уверен и не могу найти код, который выполняет такие.

Так будет ли он навсегда застрять в базе данных?

Rarst
источник
теоретически они должны быть удалены при запуске cron (если срок их действия истек)
onetrickpony
1
@ Амбициозная амеба, да, я упомянул об этом. Моя точка зрения - временное создание не предполагает и не гарантирует, что оно когда-либо будет запрошено. Подчеркивая исходный вопрос - когда и если просроченный переходный процесс удаляется, если я его никогда не получу ?
первое
1
Предполагается, что вы очистите просроченные данные, но да, вы правы, есть ситуации, в которых они никогда не будут удалены. Как удаление виджета, который использует переходные процессы. Вы должны представить билет на трак для этого :)
onetrickpony
1
@Rarst - Похоже на идеальную вещь, чтобы написать патч и отправить в trac?
MikeSchinkel
1
Билет по теме: core.trac.wordpress.org/ticket/20316
Стивен Харрис,

Ответы:

45

Они сейчас

Начиная с WordPress 3.7, при обновлении базы данных удаляются просроченные переходные процессы, см. # 20316


Старый ответ

Если кто-то не может показать мне иначе, кажется, что переходные процессы не являются мусором в конце концов. Хуже всего то, что в отличие от опций они не гарантированно хранятся в базе данных. Так что нет надежного способа получить список всех переходных процессов, чтобы проверить их на срок действия.

Некоторый временный код для сборки мусора, если база данных используется для хранения:

add_action( 'wp_scheduled_delete', 'delete_expired_db_transients' );

function delete_expired_db_transients() {

    global $wpdb, $_wp_using_ext_object_cache;

    if( $_wp_using_ext_object_cache )
        return;

    $time = isset ( $_SERVER['REQUEST_TIME'] ) ? (int)$_SERVER['REQUEST_TIME'] : time() ;
    $expired = $wpdb->get_col( "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout%' AND option_value < {$time};" );

    foreach( $expired as $transient ) {

        $key = str_replace('_transient_timeout_', '', $transient);
        delete_transient($key);
    }
}
Rarst
источник
$ time = $ _SERVER ['REQUEST_TIME']; и затем используя $ time в запросе SQL - не делайте этого. Обращайтесь с переменными / значениями $ _SERVER более осторожно, чтобы избежать SQL-инъекций.
Хакре
@hakre хм ... Я выбрал это из представления о производительности PHP, который рекомендовал использовать его, time()что может привести к ошибкам (выполнение не является мгновенным по своей природе). Время запроса устанавливается самим PHP, а не из каких-либо предоставленных пользователем данных. Почему эта уязвимость?
Rarst
@Rarst: Я не говорил, что вы не должны его использовать, вы просто должны убедиться, что он безопасно закодирован для использования внутри SQL-запроса. Вы должны сделать это с каждой переменной из внешнего источника. Переменные $ _SERVER могут быть установлены не так, как ожидается, а вместо этого могут быть установлены даже запрашивающим пользователем. Я только хотел распространить хорошую практику кодирования. Как всегда, чтобы узнать о реальном состоянии доступности, ознакомьтесь с документами. Например, для PHP 4 такая переменная не существует и может быть перезаписана пользовательским заголовком или переменной среды - php.net/manual/en/reserved.variables.server.php
hakre
@hakre исправлено (я думаю), спасибо за напоминание PHP4 (кстати, я не могу дождаться, когда WordPress
откажется
Это выглядит намного лучше в моих глазах;). Будем надеяться, что нет проблем с time () и отрицательными целыми числами, которые могут удалить все переходные процессы или вообще не создавать их, чем случайно. Никогда не доверяйте работающей системе: P
hakre
20

Перемещение некоторых комментариев из обсуждения в ответ с переписыванием и переформатированием.

По сути, это сводится к тому, что если у вас нет крайнего крайнего случая, их на самом деле не нужно «собирать». Если вы никогда их не получите, тогда не имеет значения, есть они там или нет.

Смотрите, переходные процессы хранятся в таблице параметров по умолчанию. При базовой установке таблица параметров будет содержать около 100 записей. Каждый переход добавляет еще две записи, но даже если у вас их тысячи, они не влияют на скорость сайта, поскольку они не загружаются автоматически.

При запуске WordPress загружает опции в память, но загружает только те опции, у которых включен флаг автозагрузки. Переходные процессы не получают этого, и поэтому не загружаются в память. Только переходные процессы, которые фактически используются позже, будут нести расходы.

С точки зрения базы данных таблица параметров имеет индексы как для идентификатора опции, так и для имени опции. Переходные процессы всегда загружаются на основе имени (ключа), поэтому их поиск всегда выполняется простым выбором значения уникального ключа. Таким образом, поиск O (log (n)) и очень быстрый. С Big-O log (n) вам нужно будет пройти миллионы и миллионы строк, прежде чем он станет заметным. Честно говоря, накладные расходы на настройку и разбор запроса, а также фактическую передачу данных намного больше. Сам запрос выполняется практически в нулевое время по сравнению. Так что просто наличие дополнительных неиспользуемых строк ни на что не влияет, но использует дополнительное дисковое пространство.

Индексирование в базах данных - это одна из тех идей для глубокого чтения, которая не имеет смысла для людей, которые на самом деле не понимают, что происходит за кулисами. Базы данных предназначены для быстрого извлечения данных с нуля и могут справляться с подобными вещами без проблем. Это очень хорошее чтение: http://en.wikipedia.org/wiki/Index_(database )

Теперь очистка наиболее очевидным способом (вызывая SQL DELETE для них) фактически не удаляет их из базы данных. Он просто удаляет их из индекса и помечает строку как «удаленную». Опять же, это просто, как работают базы данных. Чтобы на самом деле очистить дисковое пространство, вы должны затем продолжить и выполнить OPTIMIZE TABLE впоследствии, и это не будет быстрой операцией. Это требует времени. Наверное, больше времени, чем это стоит. Возможно, этого недостаточно для экономии процессорного времени.

Если у вас есть случай, который вызывает постоянную вставку новых переходных процессов, которые не используются, вам нужно найти основную проблему вместо этого. Что вставляет эти переходные процессы? Они используют изменяющий или мутирующий ключ? Если так, то плагин или код, вызывающий это, должны быть исправлены, чтобы, по сути, не делать этого. Это будет более полезным, поскольку вполне вероятно, что код, который не создает их должным образом, также не извлекает их и, следовательно, выполняет больше работы, чем должен.

С другой стороны, может быть случай, когда для каждого сообщения создаются переходные процессы. Это действительно может быть вполне приемлемым. Я делаю это сам в SFC, чтобы хранить входящие комментарии из Facebook. С каждым постом связан потенциальный переходный процесс, что означает две дополнительные строки на пост. Если у вас есть 10 000 записей, у вас будет 20 000 строк в таблице параметров (в конце концов). Это не плохо или медленно, потому что опять же, между 100 строками и 20000 строками очень мало различий, насколько это действительно важно для баз данных. Это все проиндексировано. Это быстро, как черт. Суб-суб-миллисекунды.

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

эфирное масло
источник
1
NB: переходные процессы без срока действия действительно загружаются, и срок действия по умолчанию не задан, поэтому, когда приложение / плагин создает много переходных процессов и не устанавливает срок действия, они будут использовать куски памяти при каждой загрузке страницы / публикации.
webaware
Нет причин использовать «переходный процесс без истечения срока действия», потому что он в основном идентичен обычному «варианту».
Отто
1
Конечно, но это по умолчанию . Таким образом, многие авторы плагинов добавляют нестационарные переходные процессы.
webaware
1
Ну, решение здесь простое: не используйте эти плагины. Они делают это неправильно. Переходные процессы не должны использоваться в качестве сеансов, вы не должны использовать их без значительного истечения срока действия, и у них не должно быть мутирующих или меняющихся ключей.
Отто
2
Скажем, 7 дней. Если автор плагина / темы хочет что-то большее или меньшее, они его укажут. Если они хотят автозагрузку, им не нужно указывать 0 для срока действия (= бесконечность), но это то, что они в настоящее время получают, когда параметр expiration выполняет двойную функцию в качестве параметра автозагрузки да / нет. В любом случае, истечение срока действия по умолчанию также не должно приводить к autoload = yes по умолчанию; это просто напрашивается на неприятности.
webaware
18

Отто - я не могу с тобой не согласиться. Проблема в том, что в конечном итоге со всеми этими переходными процессами размер таблицы становится смешным. Это не займет миллионы строк, чтобы увязнуть. В настоящее время я имею дело с таблицей опций, которая содержит более 130 тыс. Строк и регулярно зависает. Поскольку поле значения имеет большой текстовый тип, даже поиск только строк «автозагрузки» становится кошмаром производительности. Эти поля значений хранятся отдельно от остальных данных строки. Несмотря на то, что это логически является частью одной и той же таблицы, объединения должны происходить, чтобы получить нужные вам строки. Объединения, которые теперь выполняются вечно, потому что нужные вам данные распределены по всему месту на диске. Профилирование (использование струйного профилировщика для MySQL) доказало это.

Добавление автоматической загрузки в кластерный ключ может помочь решить эту проблему. Кластеризация в Autoload Desc, например, с идентификатором ASC, позволила бы сначала объединить все строки автозагрузки на диске. Даже все же я думаю, что вы смотрите на огромную нагрузку с точки зрения БД.

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

Myke
источник
5
правда, но учтите, что когда началась разработка WordPress, никто не думал, что она достигнет тысяч плагинов, использующих таблицу параметров в качестве хранилища данных :)
onetrickpony
@onetrickpony, поэтому важно всегда не торопиться и делать все правильно, ожидаете ли вы когда-нибудь, что оно будет огромным или нет :)
Махмуд Аль-Кудси