必须同时修改[client]、[mysql]、[mysqld]三段并重启验证,确保character_set_client、connection、results、server四项全为utf8mb4,且应用连接串显式声明charset=utf8mb4。

改配置文件三处段落并重启,不验证等于没改;仅执行 SQL 或只改 character-set-server 无效。
必须同时修改 [client]、[mysql]、[mysqld] 三段
MySQL 字符集生效依赖客户端、服务端、连接会话三层协同,缺一不可。只在 [mysqld] 段写 character-set-server = utf8mb4,会导致命令行连得上但插入 emoji 仍是问号。
-
[client]:影响所有客户端工具(mysql、mysqldump),加default-character-set = utf8mb4 -
[mysql]:专用于mysql命令行客户端自身,不加它,CLI 可能仍用utf8解析输入 -
[mysqld]:设服务端默认值,必须配齐两项:character-set-server = utf8mb4和collation-server = utf8mb4_0900_ai_ci(别用utf8mb4_unicode_ci)
重启后必须验证四个变量全为 utf8mb4
配置写对 ≠ 生效。Linux 下若用 mysql -u root -p 连,STATUS 显示 via socket,可能跳过 [client] 段;Windows 或宝塔用户常见路径错误(如改了 C:\Program Files\... 里的 my.ini,实际加载的是 C:\ProgramData\MySQL\...)。
- 连接后立即执行:
SHOW VARIABLES LIKE 'character\_set%'; - 必须全部满足:
character_set_client、character_set_connection、character_set_results、character_set_server四项全为utf8mb4 - 任一项是
utf8(即 utf8mb3)或latin1,说明某段配置未加载——常见于段落名拼错(比如写成[mysqld_safe])、权限不对(Docker 中 my.cnf 权限不是 644)、或被多个配置文件覆盖
ALTER DATABASE 和 ALTER TABLE CONVERT TO 不会自动升级字段定义
character-set-server 只影响新库新表,默认不触碰已有对象。即使表结构显示 CHARACTER SET utf8mb4,字段定义里若硬编码了 CHARACTER SET utf8,CONVERT TO 也会跳过该字段。
- 先改库:
ALTER DATABASE db_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci; - 再改表:
ALTER TABLE tbl_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; - 若仍有字段乱码,单独改列:
ALTER TABLE tbl_name MODIFY column_name TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; - 注意:含索引的
VARCHAR字段若长度超限(如VARCHAR(255)+ utf8mb4 → 实际需 1020 字节),需配合ROW_FORMAT=DYNAMIC和innodb_large_prefix=ON
应用连接串必须显式声明 charset=utf8mb4
服务端配再全,应用层不声明字符集,照样存不进 emoji。JDBC、PyMySQL、PDO 都要自己加参数,不能依赖服务端“默认”。
- JDBC:
jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf8mb4 - PyMySQL:
charset='utf8mb4'参数传进connect() - PHP PDO:
charset=utf8mb4写进 DSN,或执行SET NAMES utf8mb4(但不如 DSN 稳定) - Navicat / DBeaver:连接设置里手动选
utf8mb4,别用“自动”
最容易被忽略的是:init_connect='SET NAMES utf8mb4' 对 root 或 SUPER 用户不生效,而很多自动化脚本、备份任务用的就是 root;这类连接必须靠客户端段配置或连接串兜底。


















