必须同步配置client、mysql、mysqld三段并设init_connect和skip-character-set-client-handshake=OFF,再验证5个character_set变量全为utf8mb4,否则新库仍乱码或emoji插入失败。

安装 MySQL 8.0 时就配对 utf8mb4,比装完再改更可靠——但**仅在 [mysqld] 段写 character-set-server = utf8mb4 是无效的**,必须同步覆盖客户端、连接会话、校对规则、甚至时区,否则新库建出来仍是乱码或 emoji 插入失败。
安装前必须写全的 my.cnf / my.ini 三段配置
MySQL 启动时按顺序读取多个配置段,缺一不可。Windows 用户注意路径(如 C:\phpEnv\MySQL\my.ini 或 C:\ProgramData\MySQL\MySQL Server 8.0\my.ini),Linux 用户通常为 /etc/my.cnf 或 /etc/mysql/my.cnf:
-
[mysqld]段:服务端核心配置character-set-server = utf8mb4collation-server = utf8mb4_0900_ai_ciinit_connect = 'SET NAMES utf8mb4'(对普通用户生效,root 不触发)skip-character-set-client-handshake = OFF(设为ON会强制忽略客户端声明的 charset) -
[client]段:影响所有客户端工具(mysql、mysqldump)default-character-set = utf8mb4 -
[mysql]段:专用于mysql命令行客户端自身default-character-set = utf8mb4
别漏掉 init_connect 和 skip-character-set-client-handshake = OFF——它们是防止连接层退回到 utf8 或 latin1 的关键防线。
Docker、Windows MSI、宝塔等场景的特殊处理
不同安装方式加载配置的机制差异极大,不按规则来,配置文件写了也等于没写:
- Docker:必须挂载自定义
my.cnf到容器内/etc/mysql/my.cnf(不是/etc/my.cnf),且权限必须是644,否则 mysqld 静默跳过 - Windows MSI 安装包:图形向导不暴露配置编辑入口,需用命令行静默安装 + 预置
my.ini:msiexec /i mysql-installer-community-8.0.xx.msi /quiet CONFIGTYPE=configTypeServer INI_FILE="C:\mysql\my.ini" - 宝塔面板:进【软件商店】→ MySQL → 【设置】→ 【配置修改】,手动补全
[client]和[mysql]段,否则 phpMyAdmin 默认仍走utf8
验证是否被读取:Linux 下运行 mysqld --verbose --help | grep "character-set-server";Windows 下可用 mysqld --print-defaults 查看实际加载项。
安装后第一件事:验证五个变量是否全为 utf8mb4
重启服务后,用 mysql -u root -p 登录,立刻执行:
SHOW VARIABLES LIKE 'character\_set%';
必须全部满足以下五项才真正生效:
-
character_set_client= utf8mb4 -
character_set_connection= utf8mb4 -
character_set_results= utf8mb4 -
character_set_database= utf8mb4(当前库默认值) -
character_set_server= utf8mb4
只要其中任意一个不是 utf8mb4,说明链路某处断了——常见于配置写错段落(比如误塞进 [mysqld_safe])、路径不对、或被其他同名配置覆盖。此时不要继续建库建表,先定位配置加载问题。
已有数据迁移不是“一劳永逸”,字段级定义必须显式覆盖
即使配置全对、重启成功,旧库旧表的字段仍保留原字符集(如 utf8 或 latin1)。ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4 可能跳过字段,因为 MySQL 优先信任列级定义:
- 先改库:
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 VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
执行后务必用 SHOW CREATE TABLE tbl_name; 确认字段定义里明确写了 CHARACTER SET utf8mb4,而不是留空或写 utf8——这才是真正落地的标志。
最容易被忽略的是:init_connect 对 root 用户不生效,而安装后首次登录几乎都是 root;另外,utf8mb4_0900_ai_ci 和 utf8mb4_unicode_ci 行为差异会影响唯一索引判断,不能只看“能存”,还要看“怎么比”。


















