必须同时配置[mysqld]、[client]、[mysql]三段:[mysqld]设character-set-server=utf8mb4,[client]和[mysql]设default-character-set=utf8mb4,否则连接层字符集不匹配仍会报Incorrect string value错误。

只改 [mysqld] 段的 character-set-server=utf8mb4 是无效的——你看到新表还是 utf8、插入 emoji 报 Incorrect string value: '\xF0\x9F\x98\x80',大概率就是漏了其他两段配置。
my.cnf 必须同时写三段,缺一不可
MySQL 的字符集控制是分层的:客户端工具、命令行自身、服务端各自读取不同配置段。只动 [mysqld] 只影响新库/新表默认值,不影响连接时的会话字符集。
-
[client]段加default-character-set = utf8mb4:让mysql、mysqldump、mysqladmin等所有客户端工具默认用 utf8mb4 连接 -
[mysql]段加default-character-set = utf8mb4:专用于mysql命令行客户端(不写它,即使[client]有效,mysql自身也可能 fallback 到utf8) -
[mysqld]段加character-set-server = utf8mb4和collation-server = utf8mb4_0900_ai_ci(MySQL 8.0+ 推荐)或utf8mb4_unicode_ci(5.7 兼容):决定新数据库/新表的默认字符集和排序规则
MySQL 8.0 还要加 init_connect 才算真正闭环
即使三段都配了,普通用户连接后 character_set_client 仍可能不是 utf8mb4——尤其搭配 caching_sha2_password 认证时,握手阶段没显式声明就容易回退。
- 在
[mysqld]段追加init_connect = 'SET NAMES utf8mb4':让每个普通用户连接成功后自动执行该语句 - 注意:
init_connect对root或有SUPER权限的用户不生效,测试时别用 root 账号验证 - 如果应用用的是 JDBC、pymysql 等驱动,它们通常会自己发
SET NAMES,但加了更保险;Navicat 等 GUI 工具也依赖这个兜底
重启后怎么确认真生效?别只看 character_set_server
执行 SHOW VARIABLES LIKE 'character_set%'; 后,必须同时满足这四个值全为 utf8mb4:
character_set_clientcharacter_set_connectioncharacter_set_resultscharacter_set_server
只要其中一个是 latin1 或 utf8(非 utf8mb4),说明某处配置没加载,或被多个 my.cnf 路径覆盖。常见干扰项:
- Linux 下用
mysql -u root -p登录,默认走 socket 连接,[client]段可能未生效;换成mysql -h 127.0.0.1 -u root -p强制走 TCP 再查 - 用
mysqld --verbose --help | grep "Default options"查 MySQL 实际加载的配置路径,确认你改的是那个文件 - Docker 环境下,挂载的
my.cnf权限必须是644,否则 mysqld 会静默跳过
配置只是起点,已有数据库和表不会自动升级,ALTER DATABASE ... CHARACTER SET utf8mb4 和后续逐表 ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4 是绕不开的步骤——但那是另一回事了。


















