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 не менять дефолт базы (для теста на одной таблице)

Порядок работы со скриптом:

  1. Тест на одной таблице: php fix_charset.php --apply --skip-db --table=b_abtest.
  2. Убедиться через SHOW CREATE TABLE, что utf8mb4 появился и у таблицы, и у колонок.
  3. Прогон на всю базу: 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 "DESCRIPTION mediumtext ..." не соответствует описанию на диске "DESCRIPTION text ..."

Скрипт 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 — Ok
  • check_mysql_db_charsetCHARSET=utf8mb4, COLLATION=utf8mb4_unicode_ci
  • check_mysql_table_charset — Ok
  • check_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-ы для финальной правки структуры БД
Дамп базы Страховочный бэкап до начала миграции

Выводы

  1. На MySQL 8.0.x до версии 8.0.30 привести колонки к utf8mb3 физически невозможно из-за нормализации алиасов сервером. Единственный корректный путь устранения ошибок битриксового чекера по кодировкам — миграция на utf8mb4.
  2. CONVERT TO CHARACTER SET utf8mb4 автоматически расширяет типы TEXT → MEDIUMTEXT → LONGTEXT. После конвертации типы нужно вернуть к эталонным значениям, чтобы чекер структуры БД был чист.
  3. Кодировка соединения в Битриксе задаётся в двух местах — SET NAMES и collation_connection. Оба должны быть в utf8mb4 / utf8mb4_unicode_ci, иначе character_set_connection откатывается в utf8mb3.
  4. Битриксовый чекер сам генерирует SQL для устранения оставшихся расхождений структуры в своём лог-файле — писать парсер не требуется.
  5. Миграция на utf8mb4 — правильное решение и в перспективе: utf8mb3 официально deprecated, а utf8mb4 даёт поддержку 4-байтовых символов (эмодзи, редкие иероглифы).

Проверено на: 1С-Битрикс (Управление сайтом), MySQL 8.0.25 (Percona Server), PHP 8.1