MySQL 5.7+ 中需全链路升级 utf8mb4 才支持 Emoji,因 utf8 最多存 3 字节,而 Emoji 需 4 字节;须统一配置 character-set-server、collation-server 和 init_connect,并重启验证;ALTER TABLE 转换时注意索引长度超限,可改用 VARCHAR(191)。
MySQL 5.7+ 中
不支持 Emoji,必须切到
mysql 的
是个历史包袱——它最多只存 3 字节字符,而 emoji(如 ?、??)需要 4 字节,直接存会截断或报错
。这不是配置没生效,是底层编码能力根本不够。必须全链路升级到
,包括服务端、数据库、表、列、连接,缺一不可。
修改
后重启不生效?检查这三处配置是否一致
很多人改了
段的
就以为完事,结果建新表还是
。关键在三个地方必须统一:
(服务级默认)
(排序规则,推荐
或
)
(确保普通用户连接时自动设置,但注意:对
或有
权限的用户无效)
改完必须重启 MySQL,用
和
双重确认。
的坑:索引长度超限
执行转换语句后可能报错
,尤其在
加了索引的字段上。因为
下单字符最多占 4 字节,255×4 = 1020 字节,超过 InnoDB 单索引键 767 字节(旧版本)或 3072 字节(5.7.7+ 配合
)限制。
临时解法:缩短字段长度,比如
(191×4 = 764
根治法:确认
、
、
,再用
重建表
别漏掉
类型字段——它们不会因转换自动变
,需显式指定
应用层连接参数不配
,前面全白干
即使数据库全改成
,如果应用连接时没声明字符集,MySQL 仍按默认(可能是
或旧
)解析请求,Emoji 传进去就乱码或丢弃。
PHP PDO:DSN 加
,例如
Python PyMySQL:初始化时传
Java JDBC URL:加
Node.js mysql2:配置项设
最易忽略的是 ORM 默认行为——Django 的
、Laravel 的
和
都要显式写,不能依赖数据库全局设置。
真正麻烦的不是改配置,而是验证每个环节:服务端变量、库/表/列的
和
、连接时的
/
/
,三者必须全是
。少一个,Emoji 就可能悄无声息地变问号或报错。
utf8utf8mb4utf8incorrect string valueutf8mb4my.cnf[mysqld]character-set-server=utf8mb4utf8character-set-server=utf8mb4collation-server=utf8mb4_unicode_ciutf8mb4_unicode_ciutf8mb4_0900_as_csinit_connect='SET NAMES utf8mb4'rootSUPERSHOW VARIABLES LIKE 'character_set%';SHOW VARIABLES LIKE 'collation%';ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4Specified key was too longVARCHAR(255)utf8mb4innodb_large_prefix=ONVARCHAR(191)innodb_file_format=Barracudainnodb_file_per_table=ONinnodb_large_prefix=ONROW_FORMAT=DYNAMICTEXTutf8mb4MODIFY COLUMNcharset=utf8mb4utf8mb4latin1utf8;charset=utf8mb4mysql:host=localhost;dbname=test;charset=utf8mb4charset='utf8mb4'?characterEncoding=utf8mb4&useUnicode=truecharset: 'utf8mb4'OPTIONS={'charset': 'utf8mb4'}charsetcollationCHARACTER SETCOLLATIONcharacter_set_clientcharacter_set_connectioncharacter_set_resultsutf8mb4