🔤
Хостинг

utf8mb4: как сохранить эмодзи и узбекские буквы в MySQL без искажений

10.11.2026
← Все статьи

Покупатель оставил отзыв на сайте, добавил в конце улыбающийся смайлик и нажал «Отправить». В результате отзыв либо не сохраняется, либо вместо эмодзи появляются четыре вопросительных знака, либо текст обрывается ровно на этом месте. Такое чаще всего встречается в старых или неправильно настроенных базах MySQL, и причина почти всегда одна: таблица или соединение работают не в кодировке utf8mb4. В этой статье разберём, откуда берётся проблема, как она касается узбекского алфавита и как безопасно перевести базу.

«utf8» в MySQL — это не полноценный UTF-8

В стандарте UTF-8 один символ занимает от 1 до 4 байт. Латиница и цифры — 1 байт, кириллица (включая ў, қ, ғ, ҳ) — 2 байта, многие специальные символы — 3 байта, а эмодзи и часть редких иероглифов — 4 байта. Исторически MySQL под именем utf8 реализовал урезанный вариант, который хранит символы не длиннее 3 байт; в современной документации он называется utf8mb3. Полноценный UTF-8 в MySQL называется utf8mb4.

Поэтому если таблица создана в utf8, четырёхбайтовый символ в неё просто не помещается. В строгом режиме (strict mode) запрос завершается ошибкой, в нестрогом символ заменяется вопросительным знаком или строка обрезается. В журнале ошибок обычно видно примерно следующее:

SQLSTATE[HY000]: General error: 1366 Incorrect string value: '\xF0\x9F\x98\x80' for column 'comment' at row 1

Байты \xF0\x9F\x98\x80 — это и есть смайлик в кодировке UTF-8. Данные пришли корректно, просто столбец не смог их вместить.

Где на самом деле ломаются узбекские буквы

Многие думают, что узбекские oʻ и gʻ ломаются так же, как эмодзи, но ситуация другая. Буквы o' и g', набранные обычным апострофом, состоят из однобайтовых символов, специальный знак ʻ (U+02BB) занимает 3 байта, кириллические ў и қ — по 2 байта. Все они нормально хранятся даже в таблице utf8 (mb3). Узбекский текст обычно портится по другой причине: таблица создана в latin1 или cp1251, либо PHP не указывает кодировку при подключении к базе. Тогда кириллица записывается как «????», и восстановить её потом уже невозможно.

Итог простой: переход на utf8mb4 закрывает сразу две проблемы — эмодзи и прочие четырёхбайтовые символы начинают сохраняться, а старые таблицы в latin1 приводятся к современной кодировке. Для новых проектов выбирать что-то другое нет смысла.

Как проверить текущее состояние

Перед изменениями нужно точно выяснить, в какой кодировке находятся база, таблицы и столбцы. Сделать это можно в phpMyAdmin или SQL-запросом. Следующий запрос покажет collation каждой таблицы; начало имени collation обозначает кодировку:

SELECT TABLE_NAME, TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'example_db';

SHOW VARIABLES LIKE 'character_set%';
SHOW FULL COLUMNS FROM comments;

Если вы видите latin1_swedish_ci или utf8_general_ci, нужна конвертация. Если там уже utf8mb4_unicode_ci или utf8mb4_0900_ai_ci, таблицы в порядке, и проблема, скорее всего, в настройках соединения.

Порядок перевода базы на utf8mb4

Перед любыми изменениями сделайте полную резервную копию базы. В панели хостинга это несколько кликов, по SSH используется mysqldump. Кодировку дампа важно указать явно, иначе испортиться может сам файл копии:

mysqldump --default-character-set=utf8mb4 -u example_user -p example_db > example_db_backup.sql

Затем выполняются команды для базы и каждой таблицы. CONVERT TO переводит все текстовые столбцы таблицы в новую кодировку и перекодирует существующие данные:

ALTER DATABASE example_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

ALTER TABLE comments CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE products CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Если таблиц много, удобнее не писать команды вручную, а сгенерировать их запросом. Результат копируете и выполняете отдельно:

SELECT CONCAT('ALTER TABLE `', TABLE_NAME, '` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;')
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'example_db';

Ошибка длины индекса

На старых версиях MySQL (5.6 и ниже, особенно с форматом строк COMPACT) при конвертации может появиться ошибка «Specified key was too long; max key length is 767 bytes». Причина в том, что в utf8mb4 на символ резервируется 4 байта, и индекс по столбцу VARCHAR(255) требует 1020 байт. В MySQL 5.7 и новее с форматом DYNAMIC предел вырос до 3072 байт, и проблема почти не встречается. На старом сервере обычное решение — сократить индексируемый столбец до VARCHAR(191).

Кодировка в PHP-подключении

Конвертация таблиц — только половина дела. Если приложение не сообщает кодировку при подключении, сервер использует значение по умолчанию, и эмодзи снова ломаются. Для PDO в DSN добавляется charset, для mysqli вызывается отдельный метод:

// PDO
$pdo = new PDO('mysql:host=localhost;dbname=example_db;charset=utf8mb4', $user, $pass);

// mysqli
$db = new mysqli('localhost', $user, $pass, 'example_db');
$db->set_charset('utf8mb4');

В WordPress настройка находится в wp-config.php: define('DB_CHARSET', 'utf8mb4');. В Laravel значения charset и collation в config/database.php по умолчанию уже utf8mb4, но в старых проектах их стоит проверить. Строки SET NAMES utf8 в старом коде тоже нужно заменить на SET NAMES utf8mb4.

Пример: цветочный магазин в Ташкенте

Представим службу доставки цветов в Ташкенте с сайтом misol.uz и формой заказа. Покупатели часто добавляют в текст поздравления 🌹 и 🎉. Сайт сделан несколько лет назад, таблица orders в utf8_general_ci. В итоге заказы с эмодзи не попадали в базу, и оператор их вообще не видел. Разработчик сделал резервную копию, перевёл таблицы orders и order_items через CONVERT TO, добавил charset=utf8mb4 в подключение PDO и отправил тестовый заказ. После этого поздравления стали сохраняться полностью, вместе с эмодзи.

Такую работу лучше делать в часы минимальной посещаемости: конвертация большой таблицы может занять несколько минут, и всё это время таблица может быть заблокирована. На хостинге sayt.uz с базами можно работать через phpMyAdmin, а панель открывается из кабинета sayt.uz.

Что проверить после конвертации

Последний пункт стоит подчеркнуть особо: utf8mb4 защищает будущие данные, но не возвращает уже потерянные символы. Поэтому в новом проекте правильнее всего сразу создавать базу и таблицы с utf8mb4_unicode_ci. Если остались вопросы, можно обратиться в техподдержку sayt.uz через тикет.

Похожие статьи

🚦 Ошибка «Too many connections» в MySQL: причины и решение 📁 Подключение к хостингу по SFTP через FileZilla и WinSCP 🗄️ Как создать базу данных и пользователя в ISPmanager 📦 Next.js standalone build: меньше ресурсов и деплой на маленький сервер
🌐 Язык
🇺🇿 O'zbek 🇺🇿 Ўзбек 🇷🇺 Русский ✓ 🇬🇧 English