必须同时修改my.cnf中[client]、[mysql]、[mysqld]三段并重启验证,仅改[mysqld]段character-set-server无效;[mysqld]设utf8mb4及collation-server,[client]和[mysql]设default-character-set=utf8mb4,重启后验证四个character_set变量全为utf8mb4,已有库表须手动alter转换,应用连接也需显式指定charset。

只改character-set-server或只在[mysqld]段配,90%会失效——必须三段齐改、重启验证、已有数据手动转。
my.cnf 里必须同时配 [client]、[mysql]、[mysqld] 三段
MySQL 的字符集不是“设一个就全生效”的全局开关。它在连接层、客户端工具、服务端默认值三个层面各自读取不同配置段:
-
[mysqld]段加character-set-server = utf8mb4和collation-server = utf8mb4_0900_ai_ci(MySQL 8.0+ 推荐,别用utf8mb4_unicode_ci) -
[client]段加default-character-set = utf8mb4:影响mysqldump、mysqladmin等所有客户端工具 -
[mysql]段加default-character-set = utf8mb4:专管mysql命令行客户端自身,不写它,连上后character_set_client很可能还是utf8
Windows 用户注意路径是 C:\ProgramData\MySQL\MySQL Server X.X\my.ini;Docker 必须挂载自定义 my.cnf 到 /etc/mysql/my.cnf,且权限必须是 644,否则静默跳过。
重启后必须执行 SHOW VARIABLES LIKE 'character%' 验证四值全为 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 登录时若走的是 socket 连接(STATUS 显示 via socket),[client] 段可能未生效,可强制走 TCP 测试:mysql -h 127.0.0.1 -u root -p。
已有数据库和表不会自动升级,必须手动 ALTER
character-set-server 只影响新创建的数据库和表,对已存在的完全无效。哪怕你重启后新建库,老库里的表依然保持原字符集,DESCRIBE table_name 看不出异常,但插入 emoji 会报 Incorrect string value: '\xF0\x9F\x98\x80'。
转换分两步:
- 改库默认值:
ALTER DATABASE `your_db` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; - 改表及字段:
ALTER TABLE `your_table` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;(这条语句会同时更新表默认字符集 + 所有VARCHAR/TEXT字段)
生产环境建议先用脚本生成 SQL 再人工审核,别直接跑存储过程自动执行。
应用连接也得显式指定 charset,不能依赖 init_connect
[mysqld] 里加 init_connect = 'SET NAMES utf8mb4' 是辅助手段,但它对 SUPER 权限用户无效,且无法覆盖应用层主动设置的连接参数。真正可靠的做法是:在应用连接字符串中明确指定 charset=utf8mb4(如 Python 的 pymysql.connect(..., charset='utf8mb4'),PHP 的 mysqli::set_charset('utf8mb4'))。
漏掉这一步,即使服务器和数据库都设对了,只要连接层用的是 utf8,写入的四字节字符仍会被截断或报错。











