821 слов | 5 минут
Миграция базы Битрикса с utf8 на utf8mb4 на MySQL 8.0.x
Инструкция описывает переход базы 1С-Битрикс с исторической кодировки utf8 (=utf8mb3) на utf8mb4 для устранения ошибок битриксового чекера «Проверка системы». Актуально для MySQL 8.0.x до версии 8.0.30 и совместимых сборок (Percona Server 8.0.25 и т.п.).
Симптомы
Чекер «Настройки → Инструменты → Проверка системы» выдаёт ошибки вида:
Кодировка поля "SITE_ID" таблицы "b_abtest" (utf8) отличается от кодировки базы (utf8mb3)
В SHOW CREATE TABLE видно расхождение: у колонок стоит CHARACTER SET utf8, а у самой таблицы — DEFAULT CHARSET=utf8mb3. Число подобных ошибок обычно исчисляется сотнями, поскольку затрагивает все текстовые поля во всех таблицах базы.
Почему прямая правка не работает
utf8 в MySQL — это deprecated-алиас для utf8mb3. На версиях сервера до 8.0.30 нормализация имён происходит непоследовательно: в метаданных колонок сохраняется utf8, а в табличном дефолте — utf8mb3. Любой ALTER с целевой кодировкой utf8mb3 (CONVERT TO, MODIFY COLUMN и т.п.) сервер фактически игнорирует, потому что считает исходную и целевую кодировки одинаковыми.
В результате привести колонки к utf8mb3 физически невозможно ни через ALTER, ни через правку дампа (при заливке сервер снова нормализует имена).
Единственный рабочий путь — переход на utf8mb4, потому что это реальная кодировка, а не алиас, и MySQL перезаписывает метаданные корректно.
Сравнение подходов
| Подход | Работает | Комментарий |
|---|---|---|
ALTER ... CONVERT TO utf8mb3 |
❌ | MySQL нормализует, метаданные не меняются |
MODIFY COLUMN ... CHARACTER SET utf8mb3 |
❌ | То же самое |
Правка дампа sed s/utf8mb3/utf8/ |
❌ | При заливке сервер снова нормализует |
| Патч чекера Битрикса | ⚠️ | Слетит при обновлении модуля main |
| Отключение теста | ⚠️ | Косметика, реальную проблему не решает |
| Обновление MySQL до 8.0.30+ | ✅ | Требует доступа к настройкам сервера |
| Миграция на utf8mb4 | ✅ | Рекомендуемый путь |
Что важно знать перед миграцией
- Тип TEXT автоматически поднимается при
CONVERT TO CHARACTER SET utf8mb4:TEXT → MEDIUMTEXT,MEDIUMTEXT → LONGTEXT. Данные не теряются, но чекер структуры БД начнёт ругаться на несоответствие типов. - Индексы в MySQL 8 c InnoDB и
ROW_FORMAT=DYNAMIC(дефолт) — лимит ключа 3072 байта, чего достаточно для типовой битриксовой базы. BX_UTFвdbconn.phpдолжен бытьtrue— сайт уже должен работать в UTF-кодировке.- Битрикс задаёт кодировку соединения в двух местах: команда
SET NAMESи переменнаяcollation_connection. Оба нужно синхронно перевести наutf8mb4.
Пошаговая инструкция
Шаг 1. Бэкап базы
Стандартный mysqldump с флагами --single-transaction --routines --triggers. На shared-хостингах дополнительно нужен --no-tablespaces (нет привилегии PROCESS). Проверить целостность дампа по строке -- Dump completed on ... в конце файла.
Шаг 2. Проверка предпосылок
- Убедиться, что
BX_UTF = trueвbitrix/php_interface/dbconn.php. - Опционально — проверить, нет ли B-TREE индексов, которые превысят лимит 3072 байт после конвертации. Практика показывает, что MySQL 8 нормально проходит конвертацию и без предварительной правки.
- Проверить
SHOW CREATE TABLEна паре таблиц, чтобы зафиксировать текущее состояние.
Шаг 3. Конвертация таблиц на utf8mb4
Используется скрипт fix_charset.php — кладётся в корень сайта, использует битриксовый коннект. Поддерживает флаги:
| Флаг | Назначение |
|---|---|
| без флагов | dry-run, только показать SQL |
--apply |
реально выполнить ALTER-ы |
--table=NAME |
обработать только одну таблицу (для теста) |
--skip-db |
не менять дефолт базы (для теста на одной таблице) |
Порядок работы со скриптом:
- Тест на одной таблице:
php fix_charset.php --apply --skip-db --table=b_abtest. - Убедиться через
SHOW CREATE TABLE, чтоutf8mb4появился и у таблицы, и у колонок. - Прогон на всю базу:
php fix_charset.php --apply.
Скрипт делает ALTER DATABASE для смены дефолта БД, затем ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci по каждой таблице, у которой хоть что-то не в целевой кодировке. Ошибка на одной таблице не прерывает обработку остальных — в конце выводится сводка.
Шаг 4. Смена кодировки соединения
Правятся два файла:
bitrix/php_interface/after_connect.php— для старого ядра ($DB->Query).bitrix/php_interface/after_connect_d7.php— для D7 ($this->queryExecute).
В каждом файле — две команды: SET NAMES 'utf8mb4' и SET collation_connection = 'utf8mb4_unicode_ci'.
Ключевой момент: если поменять только SET NAMES, но оставить collation_connection = utf8_unicode_ci, — переменная character_set_connection откатится в utf8mb3, потому что коллация utf8_unicode_ci принадлежит utf8mb3. Чекер выдаст ошибку «Кодировка соединения (utf8mb3) отличается от кодировки результата (utf8mb4)». Для utf8mb4 нужна коллация utf8mb4_unicode_ci.
Для диагностики переменных сессии — скрипт check_session.php, выводит SHOW VARIABLES LIKE 'character_set%' и collation% через битриксовый коннект. Все переменные должны быть в utf8mb4, коллации — в utf8mb4_unicode_ci.
Шаг 5. Уменьшение типов TEXT
После конвертации на utf8mb4 колонки TEXT автоматически расширены до MEDIUMTEXT. Битриксовый чекер структуры БД начнёт ругаться:
В таблице b_report поле DESCRIPTION "
DESCRIPTIONmediumtext ..." не соответствует описанию на диске "DESCRIPTIONtext ..."
Скрипт fix_text_types.php проходит по всем колонкам mediumtext в базе, проверяет максимальную длину данных, и если данные помещаются в TEXT (65535 байт) — уменьшает тип. Колонки с реально длинными данными пропускаются.
Использование — аналогично fix_charset.php: сначала dry-run без флагов, потом --apply.
Шаг 6. Оставшиеся расхождения структуры БД
После шагов 3–5 чекер обычно оставляет 30–50 расхождений: где Битрикс хочет mediumtext вместо получившегося longtext, а также попутные структурные фиксы (например, int → bigint для b_iblock_element_property.ID, изменение точности decimal в таблицах модуля sale).
Битриксовый чекер сам генерирует нужные ALTER-ы и пишет их в свой лог-файл bitrix/site_checker_HASH.log. Достаточно извлечь их через grep "^ALTER TABLE" в отдельный файл и прогнать через mysql < ... — писать парсер не требуется.
Шаг 7. Финальная проверка
Запустить «Проверку системы» ещё раз. Все проверки по кодировкам и структуре БД должны пройти:
check_mysql_connection_charset— Okcheck_mysql_db_charset—CHARSET=utf8mb4, COLLATION=utf8mb4_unicode_cicheck_mysql_table_charset— Okcheck_mysql_table_structure— Ok
Шаг 8. Уборка
Удалить временные скрипты (fix_charset.php, fix_text_types.php, check_session.php) из корня сайта, промежуточные логи и бэкапы конфигов в bitrix/php_interface/. Дамп базы оставить на 1–2 недели для страховки.
Артефакты миграции
| Артефакт | Назначение |
|---|---|
fix_charset.php |
Конвертация таблиц и дефолта БД на utf8mb4 |
check_session.php |
Диагностика переменных кодировки в сессии подключения |
fix_text_types.php |
Уменьшение mediumtext → text после конвертации |
| Лог чекера | Готовые ALTER-ы для финальной правки структуры БД |
| Дамп базы | Страховочный бэкап до начала миграции |
Выводы
- На MySQL 8.0.x до версии 8.0.30 привести колонки к
utf8mb3физически невозможно из-за нормализации алиасов сервером. Единственный корректный путь устранения ошибок битриксового чекера по кодировкам — миграция наutf8mb4. CONVERT TO CHARACTER SET utf8mb4автоматически расширяет типыTEXT → MEDIUMTEXT → LONGTEXT. После конвертации типы нужно вернуть к эталонным значениям, чтобы чекер структуры БД был чист.- Кодировка соединения в Битриксе задаётся в двух местах —
SET NAMESиcollation_connection. Оба должны быть вutf8mb4/utf8mb4_unicode_ci, иначеcharacter_set_connectionоткатывается вutf8mb3. - Битриксовый чекер сам генерирует SQL для устранения оставшихся расхождений структуры в своём лог-файле — писать парсер не требуется.
- Миграция на
utf8mb4— правильное решение и в перспективе:utf8mb3официально deprecated, аutf8mb4даёт поддержку 4-байтовых символов (эмодзи, редкие иероглифы).
Проверено на: 1С-Битрикс (Управление сайтом), MySQL 8.0.25 (Percona Server), PHP 8.1