Orphaned meta — это строки в таблицах метаданных, для которых больше нет связанной записи, пользователя или термина. Например, запись удалили, а её данные остались в wp_postmeta. Такие строки могут накапливаться после удаления контента или некорректной работы плагина.
Найти и удалить их можно SQL-запросами, но сначала нужно проверить найденные строки и сделать резервную копию базы. Не путайте orphaned meta с метаданными плагина, который уже удалён: если у строки есть действующий объект WordPress, она не является осиротевшей только потому, что вы не узнаёте её ключ.
Какие метаданные считать осиротевшими
В стандартной базе WordPress метаданные хранятся отдельно от основных объектов:
wp_postmetaсвязана с записями, страницами, вложениями и ревизиями изwp_posts;wp_usermetaсвязана с пользователями изwp_users;wp_termmetaсвязана с терминами изwp_terms.
Строка считается кандидатом на удаление, если в поле связи указан ненулевой ID, а объекта с таким ID уже нет. Нулевые ID лучше не удалять автоматически: плагины могут использовать их для собственных данных. Метаданные ревизий тоже не orphaned, если сама ревизия ещё есть в wp_posts.
Запросы ниже рассчитаны на стандартную структуру WordPress. Замените префикс wp_ на префикс таблиц вашего сайта: он может отличаться. Если таблицы wp_termmeta нет, пропустите проверку метаданных терминов.
Перед очисткой сделайте резервную копию
Удаление строк из базы необратимо, если у вас нет подходящей копии. Перед SQL-запросами создайте резервную копию базы через панель хостинга, phpMyAdmin или используемое вами средство резервного копирования. Убедитесь, что копия действительно создана и доступна для восстановления. Для важного или рабочего сайта сначала проверьте процедуру на копии сайта.
Далее запросы можно запускать в phpMyAdmin или другом клиенте MySQL. Если у вас настроен WP-CLI, SQL можно выполнить командой wp db query, но доступность этой команды зависит от хостинга и конфигурации WP-CLI. Если вы не уверены, как восстановить базу, не запускайте запросы на рабочем сайте без помощи администратора.
Сначала посмотрите, какие строки будут затронуты
Начните с подсчёта и просмотра примеров. Запросы только читают данные и ничего не удаляют. Выполняйте те из них, для которых соответствующая таблица есть в вашей базе.
SELECT COUNT(*) AS orphan_count
FROM wp_postmeta AS pm
LEFT JOIN wp_posts AS p ON p.ID = pm.post_id
WHERE p.ID IS NULL AND pm.post_id <> 0;
SELECT pm.meta_id, pm.post_id, pm.meta_key, LEFT(pm.meta_value, 200) AS value_sample
FROM wp_postmeta AS pm
LEFT JOIN wp_posts AS p ON p.ID = pm.post_id
WHERE p.ID IS NULL AND pm.post_id <> 0
LIMIT 50;Так вы проверите метаданные записей. Значения в meta_value могут содержать сериализованные данные, поэтому не редактируйте их вручную без понимания формата. Для поиска достаточно посмотреть ID, ключ и короткий фрагмент значения.
Проверка пользовательских метаданных:
SELECT COUNT(*) AS orphan_count
FROM wp_usermeta AS um
LEFT JOIN wp_users AS u ON u.ID = um.user_id
WHERE u.ID IS NULL AND um.user_id <> 0;
SELECT um.umeta_id, um.user_id, um.meta_key, LEFT(um.meta_value, 200) AS value_sample
FROM wp_usermeta AS um
LEFT JOIN wp_users AS u ON u.ID = um.user_id
WHERE u.ID IS NULL AND um.user_id <> 0
LIMIT 50;А для метаданных терминов запрос сравнивает их с таблицей wp_terms:
SELECT COUNT(*) AS orphan_count
FROM wp_termmeta AS tm
LEFT JOIN wp_terms AS t ON t.term_id = tm.term_id
WHERE t.term_id IS NULL AND tm.term_id <> 0;
SELECT tm.meta_id, tm.term_id, tm.meta_key, LEFT(tm.meta_value, 200) AS value_sample
FROM wp_termmeta AS tm
LEFT JOIN wp_terms AS t ON t.term_id = tm.term_id
WHERE t.term_id IS NULL AND tm.term_id <> 0
LIMIT 50;Если запрос показывает строки, проверьте несколько примеров и убедитесь, что в таблице указано правильное соответствие ID. Не удаляйте данные только по незнакомому meta_key: действующие темы и плагины могут хранить там настройки, нужные сайту.
Удалите подтверждённые orphaned meta
Когда вы проверили результаты и сохранили резервную копию, выполните соответствующие запросы удаления. Каждый удаляет только строки без родительского объекта с ненулевым ID.
DELETE pm
FROM wp_postmeta AS pm
LEFT JOIN wp_posts AS p ON p.ID = pm.post_id
WHERE p.ID IS NULL AND pm.post_id <> 0;
DELETE um
FROM wp_usermeta AS um
LEFT JOIN wp_users AS u ON u.ID = um.user_id
WHERE u.ID IS NULL AND um.user_id <> 0;
DELETE tm
FROM wp_termmeta AS tm
LEFT JOIN wp_terms AS t ON t.term_id = tm.term_id
WHERE t.term_id IS NULL AND tm.term_id <> 0;Запускайте запросы только для существующих таблиц. Если вместо стандартного префикса у вас, например, site_, замените его во всех именах таблиц. Запросы используют синтаксис MySQL с удалением из таблицы через DELETE alias FROM ...; поддержка такого синтаксиса зависит от используемой СУБД и её версии. Если запрос отклонён, не меняйте его наугад — уточните версию MySQL или MariaDB у хостинга.
Проверьте результат и работу сайта
После удаления повторите запросы подсчёта из предыдущего раздела: для обработанных таблиц они должны вернуть ноль. Это подтверждает, что строк без соответствующего объекта больше не осталось. Затем проверьте в админке и на сайте несколько типов контента, которые могли затрагиваться, а также функции плагинов, использующих пользовательские поля, данные пользователей или термины.
Если обнаружилась проблема, восстановите базу из копии. Не пытайтесь исправить последствия массовым удалением всех строк с конкретным ключом: это может затронуть действующие объекты.
Почему orphaned meta появляется снова
Некоторые плагины при удалении своих данных удаляют метаданные самостоятельно, другие могут оставлять их в базе. Причиной также бывает неудачное удаление записей или пользователей, сбой во время операции либо собственный код сайта, который напрямую удаляет объект, не очищая связанные таблицы.
SQL-запросы устраняют накопившиеся строки, но не исправляют причину их появления. Если после очистки новые orphaned meta регулярно возникают, проверьте, после каких действий это происходит, и выясните, какой плагин или код работает с соответствующими объектами и метаполями. Не запускайте автоматическое удаление по расписанию, пока не убедились, что выбранные условия не затрагивают данные, которые сайт использует намеренно.
Если сайт работает в Multisite
В сети сайтов таблицы записей и терминов обычно имеют отдельный набор для каждого сайта, например wp_2_posts и wp_2_postmeta. Проверяйте метаданные в паре с таблицей того же сайта: запрос для одного префикса не очистит остальные сайты сети. Пользовательские таблицы в Multisite устроены иначе: wp_users и wp_usermeta общие для сети, поэтому сверять их нужно с общей таблицей пользователей, а не с таблицами конкретного сайта.