MySQL默认utf8实为utf8mb3,不支持emoji;需全程升级为utf8mb4:确认版本≥5.5.3,修改my.cnf设character-set-server=utf8mb4,重建库表并转换字符集,客户端连接显式声明charset=utf8mb4。

MySQL 默认的 utf8 实际上是 utf8mb3,最多只支持 3 字节字符,根本存不了 emoji(比如 ?、❤️、??),强行插入会报错或截断。要真正支持表情符号,必须全程切换到 utf8mb4,且不能只改某一层。
确认 MySQL 版本和当前字符集配置
低于 5.5.3 的 MySQL 不支持 utf8mb4;5.5.3+ 才有完整支持。先检查:
SELECT VERSION();<br>SHOW VARIABLES LIKE 'character_set%';<br>SHOW VARIABLES LIKE 'collation%';
重点看 character_set_server、collation_server、以及你目标数据库/表的字符集。如果仍是 utf8 或 latin1,后续插入 emoji 必然失败。
修改 my.cnf 配置文件(服务端层面)
仅靠 SQL 命令临时改是没用的,重启后就还原。必须在配置文件中固化:
character-set-server = utf8mb4-
collation-server = utf8mb4_unicode_ci(推荐,比utf8mb4_general_ci更准确) -
skip-character-set-client-handshake(可选,强制客户端服从服务端设定,避免连接时被覆盖)
改完重启 MySQL:sudo systemctl restart mysql(或 mysqld)。注意:Windows 下是 my.ini,Linux/macOS 是 /etc/my.cnf 或 /etc/mysql/my.cnf,路径不统一,别改错文件。
重建数据库、表与字段(存储层)
已有数据库/表不会自动升级,必须显式转换:
- 新建库直接指定:
CREATE DATABASE db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 已有库改默认字符集:
ALTER DATABASE db_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - 已有表改字符集:
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 特别注意:如果字段是
TEXT或VARCHAR,还要检查ROW_FORMAT。InnoDB 表若用COMPACT格式且字段长度超限(如VARCHAR(255)在 utf8mb4 下实际占 1020 字节),可能触发Row size too large错误。此时需加ROW_FORMAT=DYNAMIC
客户端连接也要显式声明 utf8mb4
即使服务端全配对了,应用连接时没声明,照样存不进 emoji。不同驱动写法不同:
- PHP PDO:
$pdo = new PDO("mysql:host=localhost;charset=utf8mb4", ...);(charset=utf8mb4必须写在 DSN 里) - Python PyMySQL:
charset='utf8mb4'参数传入connect() - Node.js mysql2:
charset: 'utf8mb4'在 config 对象中 - Java JDBC URL:
?characterEncoding=utf8mb4(注意不是utf8)
漏掉这步,SET NAMES utf8mb4 这类 SQL 命令也救不了——因为连接一建立,默认就是 utf8 编码,后续所有数据传输都按它解码。
最常被忽略的是字段索引长度限制:VARCHAR(255) 在 utf8mb4 下最大索引长度是 191 字符(767 字节 / 4),超出就得调小长度或改用 innodb_large_prefix=ON + ROW_FORMAT=DYNAMIC。这点在迁移老表时几乎必踩。


















