Почему utf8 в MySQL не поддерживает emoji
MySQL реализовал кодировку utf8 как 3-байтовую, что покрывает большинство символов, но не emoji (они занимают 4 байта). При попытке сохранить emoji в utf8-колонке MySQL молча обрезает строку или возвращает ошибку. utf8mb4 — настоящая 4-байтовая UTF-8, поддерживающая полный Unicode включая emoji.
Настройка my.cnf для utf8mb4 по умолчанию
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
character-set-filesystem = utf8mb4
[mysql]
default-character-set = utf8mb4
[client]
default-character-set = utf8mb4sudo systemctl restart mysqlПроверка текущей кодировки
mysql -u root -p -e "
SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';"Изменение кодировки существующей базы данных
-- Изменить charset базы данных
ALTER DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- Изменить charset таблицы
ALTER TABLE mytable CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- Изменить колонку
ALTER TABLE mytable MODIFY content TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;Конвертация всех таблиц в базе данных
-- Генерация команд для всех таблиц
SELECT CONCAT(
'ALTER TABLE `', TABLE_NAME, '` ',
'CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;'
) AS migration_sql
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'mydb' AND TABLE_TYPE = 'BASE TABLE';Collation: unicode_ci vs general_ci vs bin
| Collation | Описание | Когда использовать |
|---|---|---|
utf8mb4_unicode_ci | Точное Unicode-сравнение (CI = case insensitive) | Большинство сайтов (рекомендуется) |
utf8mb4_general_ci | Упрощённое сравнение, чуть быстрее | Высоконагруженные проекты |
utf8mb4_bin | Побайтовое сравнение (CS = case sensitive) | Пароли, хэши, чувствительные к регистру данные |
utf8mb4_0900_ai_ci | MySQL 8.0 стандарт Unicode 9.0 | MySQL 8.0+ |
Настройка в PHP (PDO)
<?php
$pdo = new PDO(
'mysql:host=localhost;dbname=mydb;charset=utf8mb4',
'user', 'password',
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci'
]
);При обновлении с
utf8 на utf8mb4 проверьте, что индексы VARCHAR-колонок не превышают 767 байт. При utf8mb4 один символ = до 4 байт, поэтому VARCHAR(191) — максимум для индексируемых строк при стандартном InnoDB (innodb_large_prefix=OFF).