必须同时修改my.cnf中[client]、[mysql]、[mysqld]三段配置,缺一不可;仅设[mysqld]段character-set-server=utf8mb4无效,因mysql启动时分层读取各段配置,分别控制客户端工具、命令行客户端及服务端默认字符集与排序规则。

my.cnf 必须同时改三段,缺一不可
只在 [mysqld] 段写 character-set-server = utf8mb4 是无效的。MySQL 启动时分别读取 [client]、[mysql]、[mysqld] 三段配置,各自控制不同层级:
-
[mysqld]:决定新库/新表默认字符集和排序规则,必须配character-set-server = utf8mb4和collation-server = utf8mb4_0900_ai_ci(MySQL 8.0+ 推荐,别用utf8mb4_unicode_ci) -
[client]:影响所有客户端工具(如mysqldump、mysqladmin)的默认连接字符集,加default-character-set = utf8mb4 -
[mysql]:专用于mysql命令行客户端自身,也加default-character-set = utf8mb4,否则命令行连上后character_set_client仍是utf8
Windows 用户注意路径:C:\ProgramData\MySQL\MySQL Server X.X\my.ini;宝塔用户进【软件商店】→ MySQL → 【设置】→ 【配置修改】;Docker 必须挂载自定义 my.cnf 到 /etc/mysql/my.cnf,权限设为 644,否则静默跳过。
重启后必须验证四个 character_set 变量全为 utf8mb4
改完配置不验证,等于没改。连接 MySQL 后执行:
SHOW VARIABLES LIKE 'character%';
必须全部满足:
character_set_client = utf8mb4character_set_connection = utf8mb4character_set_results = utf8mb4character_set_server = utf8mb4
任一值仍是 utf8 或 latin1,说明配置未加载——常见于段落写错(比如误写到 [mysqld_safe] 下)、路径不对、或被其他同名配置覆盖。Linux 下若用 mysql -u root -p 连接后 STATUS; 显示 via socket,可能未读取 [client] 段,可强制走 TCP 测试:mysql -h 127.0.0.1 -u root -p(注意是 127.0.0.1,不是 localhost)。
已有数据库和表不会自动升级,必须手动 ALTER
character-set-server 只影响新创建的数据库和表,对已存在的完全无效。即使你改完配置、重启、新建库,老库里的表依然保持原字符集,连 DESCRIBE table_name 都看不出异常。
- 改库:
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;
注意:ALTER 操作会锁表,大表务必在低峰期执行;CONVERT TO 会重写整张表,比单纯 MODIFY 更彻底,推荐优先使用。
应用连接也需显式指定 charset
服务端和数据库层都设好了,但应用连接仍可能用错字符集。例如 PHP 的 mysqli 必须在连接后执行 mysqli_set_charset($conn, 'utf8mb4');Python 的 pymysql 要在 connect() 里传 charset='utf8mb4';Java 的 JDBC URL 加 ?characterEncoding=utf8mb4。
漏掉这一步,INSERT emoji 时大概率报错 Incorrect string value: '\xF0\x9F\x98\x80' —— 这不是服务端问题,是连接层把四字节字符当成了非法序列丢弃了。
真正容易被忽略的是:每个连接实例都要单独设置,不能只靠全局配置“一劳永逸”。尤其是长连接池、连接复用场景下,初始化逻辑稍有疏漏,就会让部分请求悄悄退回到 utf8。











