必须同时修改[client]、[mysql]、[mysqld]三段配置:[client]设default-character-set=utf8mb4,[mysql]设default-character-set=utf8mb4,[mysqld]设character-set-server=utf8mb4及collation-server=utf8mb4_0900_ai_ci(8.0+)或utf8mb4_unicode_ci(5.7)。

必须同时改三处配置,缺一不可,否则新表还是 utf8。
my.cnf 里要填哪三段?
MySQL 的 utf8mb4 不是设一个参数就全局生效。它在客户端、连接层、服务端三个层面各自独立控制,my.cnf 中必须同时配置以下三段:
-
[client]段加default-character-set = utf8mb4:影响所有客户端工具(如mysql命令行)的默认连接字符集 -
[mysql]段加default-character-set = utf8mb4:专用于mysql命令行客户端自身(不写可能被忽略) -
[mysqld]段加character-set-server = utf8mb4和collation-server = utf8mb4_0900_ai_ci(MySQL 8.0 推荐)或utf8mb4_unicode_ci(5.7 兼容):决定新库/新表的默认值
漏掉任意一段,都会导致部分环节仍用 latin1 或 utf8mb3,插入 emoji 时抛出 Incorrect string value: '\xF0\x9F\x98\x80' 就是典型表现。
重启后为什么 SHOW VARIABLES 还是 utf8?
常见错因不是配置没写对,而是 MySQL 没真正加载你改的 my.cnf。验证和排查要点:
- 查实际加载路径:
mysqld --verbose --help | grep "Default options" - Linux 下用
mysql -u root -p登录时,若 STATUS 显示via socket,说明走的是 Unix socket 连接——此时[client]段可能未生效;改用mysql -h 127.0.0.1 -u root -p强制走 TCP,再查SHOW VARIABLES LIKE 'character_set_client' - Docker 环境下,确认挂载的
my.cnf权限为644,否则 mysqld 会静默跳过
ALTER DATABASE CHARACTER SET utf8mb4 有用吗?
有用,但只改当前数据库的默认字符集,不影响已有表字段。执行后:
- 新创建的表会继承该库的
utf8mb4默认值 - 已有表的
CHARACTER SET和字段定义完全不变,DESCRIBE table_name看不出异常,但插入 emoji 仍失败 - 必须逐表执行
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci
注意:CONVERT TO 会重建表,大表需评估锁时间和磁盘空间;生产环境建议搭配 pt-online-schema-change 或选择业务低峰期操作。
为什么新建表还是 utf8mb3?
即使 character-set-server 已设为 utf8mb4,如果建表语句里显式写了 CHARACTER SET utf8,MySQL 会优先用语句里的声明。常见陷阱:
- 旧脚本或 ORM 自动生成的 DDL 含
DEFAULT CHARSET=utf8,需手动替换为utf8mb4 - 某些迁移工具(如早期版本 mysqldump)导出时默认用
--default-character-set=utf8,导出命令必须显式加--default-character-set=utf8mb4 - MySQL 8.0+ 虽默认
utf8mb4,但若连接时执行了SET NAMES utf8,后续建表仍按utf8mb3处理
最稳妥的做法:检查每个建表语句末尾是否含 DEFAULT CHARSET=utf8mb4,并确认连接建立后未被 SET NAMES 覆盖。


















