MySQL的utf8不支持emoji,因其仅支持3字节UTF-8编码;必须使用utf8mb4并同步配置服务端、连接层、数据库/表/列字符集,同时注意索引长度限制与CONVERT TO的局限性。

MySQL 的 utf8 实际上不支持 emoji
MySQL 早期实现的 utf8 字符集只支持最多 3 字节的 UTF-8 编码,而 emoji(如 ?、?、??)属于 Unicode 补充平面字符,需要 4 字节编码。所以即使字段声明为 CHARSET=utf8,插入 emoji 时会报错 Incorrect string value 或被静默截断。
必须改用 utf8mb4 并确保全链路支持
MySQL 5.5.3+ 提供了真正的 UTF-8 实现:utf8mb4。但只改表或字段字符集远远不够,需同步调整以下几处:
- 服务端配置:在
my.cnf中设置character-set-server = utf8mb4和collation-server = utf8mb4_unicode_ci - 连接层:客户端连接时显式指定
charset=utf8mb4(例如 Python 的pymysql.connect(..., charset='utf8mb4')) - 数据库/表/列:重建或修改时使用
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci - 注意索引长度限制:
utf8mb4下单个字符最多占 4 字节,原本VARCHAR(255)的索引可能超 767 字节(InnoDB 默认限制),可改用innodb_large_prefix=ON+ROW_FORMAT=DYNAMIC,或缩短字段长度
ALTER TABLE 修改时容易漏掉的细节
直接对已有表执行 ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci 看似简单,但有隐患:
- 不会自动更新列定义中的
CHARACTER SET显式声明(如果原来写了CHARSET=utf8),建议手动重写MODIFY COLUMN - TEXT 类型字段(如
MEDIUMTEXT)的排序规则(collation)可能未生效,需单独指定,例如:MODIFY content TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci - 如果表有全文索引,
CONVERT TO会失败,需先DROP FULLTEXT INDEX,改完再重建
验证是否真正生效的三个检查点
改完别急着插 emoji,先确认三处返回值一致:
- 执行
SHOW VARIABLES LIKE 'character_set%'—— 关注character_set_client、character_set_connection、character_set_database是否均为utf8mb4 - 执行
SHOW CREATE TABLE t—— 确认表和各文本列的CHARSET和COLLATE都是utf8mb4_* - 执行
SELECT CHARSET('?'), LENGTH('?'), CHAR_LENGTH('?')—— 应分别返回utf8mb4、4、1;若LENGTH是 3,说明连接层仍走的是utf8
最常被忽略的是连接时的字符集协商——哪怕服务端设对了,客户端没传 charset=utf8mb4,MySQL 仍按默认(可能是 latin1 或旧 utf8)解析请求体。


















