必须将character-set-server设为utf8mb4,否则mysql 5.7及更早版本新建数据库默认为latin1,且mysql的utf8实为utf8mb3(仅支持3字节),无法存储emoji等4字节字符;需同步配置collation-server、skip-character-set-client-handshake,并在[client]和[mysql]段落中设置default-character-set=utf8mb4,同时显式建库建表并确保连接层三字符集全为utf8mb4。

character-set-server 必须设为 utf8mb4,否则新建数据库默认仍是 latin1(MySQL 5.7 及更早版本)或不兼容 emoji 的伪 utf8。这不是“可选优化”,而是数据写入前就决定是否丢字符的硬门槛。
为什么不能只改 utf8?
MySQL 的 utf8 实际是 utf8mb3,最多存 3 字节字符;而中文生僻字、emoji、部分越南语/阿拉伯语字符需要 4 字节。utf8mb4 才是标准 UTF-8 实现。你看到的“乱码”或“”,大概率是客户端发了 4 字节字符,但服务端按 3 字节截断导致的。
my.cnf 中必须配置的三项
仅改 character-set-server 不够,以下三项要同时存在且一致:
-
character-set-server = utf8mb4:决定新数据库、新表的默认字符集 -
collation-server = utf8mb4_0900_ai_ci(MySQL 8.0+)或utf8mb4_unicode_ci(5.7):排序规则必须匹配,否则ALTER DATABASE可能失败 -
skip-character-set-client-handshake = OFF:允许客户端声明自己用的编码;设为ON会强制忽略客户端请求,反而容易出错
别漏掉 [client] 和 [mysql] 段落里的 default-character-set = utf8mb4——否则你用 mysql 命令行连上去,默认还是 latin1。
创建数据库时仍要显式指定 CHARACTER SET
即使配置文件写全了,执行 CREATE DATABASE db1; 仍可能继承旧值(尤其在未重启或配置未生效时)。保险做法是:
CREATE DATABASE db1 CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
注意:COLLATE 必须与 collation-server 一致,否则建库后 SHOW CREATE DATABASE db1; 会显示不匹配的排序规则,后续建表可能隐式降级。
ALTER DATABASE 不会自动更新已有表
执行 ALTER DATABASE db1 CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; 只改数据库元数据,不影响里面已存在的表。每张表仍需单独执行:
ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
更麻烦的是字段级:如果某 VARCHAR 字段定义时指定了 CHARACTER SET latin1,上面的 CONVERT 会覆盖它;但如果字段用了 BINARY 或 ENUM,可能需先 MODIFY 再 CONVERT,否则报错 ERROR 1833。
character_set_client、character_set_connection、character_set_results 三者必须全为 utf8mb4,缺一不可。它们不随 character-set-server 自动同步,得靠 init_connect = 'SET NAMES utf8mb4' 或应用层显式执行该语句来兜底。











