Как выглядит проблема
До
INSERT INTO wp_posts (post_title) VALUES ('Заказ готов — доставка РІ среду');После
INSERT INTO wp_posts (post_title) VALUES ('Заказ готов — доставка в среду');Откуда это берётся
WordPress хранит текст в UTF-8. Но многие старые установки создавали таблицы в latin1 или cp1251 либо подключались к базе с такой кодировкой. Пока запись и чтение делают одну и ту же ошибку, никто ничего не замечает. После переноса на новый сервер, экспорта через phpMyAdmin или смены кодировки соединения каждая русская буква вдруг превращается в два символа.
DB_CHARSETвwp-config.phpравенlatin1или не совпадает с таблицами.- Дамп экспортировали как
latin1, а импортировали какutf8mb4— или наоборот. - Плагин или скрипт импорта ещё раз перекодировал уже испорченный текст. Так возникает двойная кодировка.
Исправляем экспорт
- Сделайте резервную копию базы, прежде чем что-либо менять.
- Экспортируйте нужные таблицы в файл
.sql, например через phpMyAdmin илиmysqldump --default-character-set=utf8mb4. - Перетащите файл в поле выше. Mojibuster исправит только испорченные места и покажет каждое изменение.
- Скачайте исправленный файл и импортируйте его в чистую тестовую базу с кодировкой
utf8mb4. - Проверьте сайт. Если всё в порядке, импортируйте файл в рабочую базу.
Дамп никуда не загружается. Это важно: в нём обычно лежат учётные записи, адреса электронной почты и комментарии.
Осторожно: сериализованные данные
WordPress хранит часть настроек в wp_options и wp_postmeta в виде сериализованных значений PHP, например s:12:"Привет";. Число — это длина строки в байтах: в UTF-8 каждая русская буква занимает два байта. Испорченный текст имеет другую длину, чем исправленный, поэтому после правки число не совпадает, и WordPress отбрасывает значение. Сначала исправляйте таблицы с содержимым: wp_posts, wp_comments и wp_terms. Для настроек лучше подходит wp search-replace из WP-CLI — он пересчитывает длины.
Устраняем причину в MySQL
- Переведите таблицы и соединение на
utf8mb4и укажите вwp-config.phpстрокуdefine('DB_CHARSET', 'utf8mb4');. - Если в столбце
latin1лежат байты UTF-8, не конвертируйте его напрямую — текст закодируется второй раз. Обычный путь идёт через двоичный тип: сначалаMODIFY … LONGBLOB, затемMODIFY … LONGTEXT CHARACTER SET utf8mb4. - Каждое изменение сначала проверяйте на копии базы.
Частые вопросы
Можно ли исправить всю базу WordPress сразу?
Да, в том числе большие SQL-дампы. Но учтите сериализованные данные в wp_options и wp_postmeta — с ними лучше справляется WP-CLI.
Изменятся ли правильные символы в дампе?
Нет. Mojibuster исправляет только явно испорченные последовательности. Правильный текст остаётся как есть.
Чем отличаются utf8 и utf8mb4?
В MySQL utf8 хранит символы длиной не более трёх байт, поэтому эмодзи теряются. utf8mb4 — это настоящий UTF-8, и именно он нужен для WordPress.
Подойдёт ли это не только для WordPress?
Да. У Joomla, Drupal, Битрикса, Magento и собственных приложений на MySQL или MariaDB та же проблема и то же решение.