Как изглежда проблемът
Преди
INSERT INTO wp_posts (post_title) VALUES ('Меню РЅР° деня – шопска салата');След
INSERT INTO wp_posts (post_title) VALUES ('Меню на деня – шопска салата');Откъде идва
WordPress съхранява текста като UTF-8. Много по-стари инсталации обаче имат таблици, създадени като latin1, или се свързват с такова кодиране. Докато записът и четенето правят една и съща грешка, никой не забелязва. След преместване на нов сървър, експорт с 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:14:"Здравей";. Числото е дължината в байтове. Когато Р№ отново стане й, дължината вече не съвпада и 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 имат същия проблем и същото решение.