答案是必须统一客户端、连接层、服务端、数据库、表五层字符集为utf8mb4;执行show variables like 'character\_set%'和show variables like 'collation%'确认character_set_client、connection、results、server四值全为utf8mb4,缺一不可。

确认当前字符集配置是否全链路统一
乱码不是孤立现象,而是客户端、连接、服务端、数据库、表五层字符集不一致的综合结果。只改其中一层,比如只把表设成 utf8mb4,但 character_set_client 还是 latin1,照样出错。
执行以下命令一次性查清关键变量:
SHOW VARIABLES LIKE 'character\_set%';<br>SHOW VARIABLES LIKE 'collation%';
重点关注这四个值必须一致(推荐全为 utf8mb4):
character_set_clientcharacter_set_connectioncharacter_set_resultscharacter_set_server
如果其中任意一项是 latin1 或 utf8(注意不是 utf8mb4),就说明链路已断裂。
修改 my.cnf 或 my.ini 配置文件(服务端持久化设置)
仅靠会话级 SET 命令只能临时生效,重启 MySQL 后失效。必须从配置文件入手,确保每次启动都按预期加载。
在 [mysqld] 段添加:
[mysqld]<br>character-set-server = utf8mb4<br>collation-server = utf8mb4_unicode_ci
在 [client] 段添加:
[client]<br>default-character-set = utf8mb4
⚠️ 注意事项:
- Windows 下配置文件名通常是
my.ini,Linux 下是/etc/my.cnf或/etc/mysql/my.cnf - 不要写成
utf-8或UTF8MB4—— MySQL 只认小写utf8mb4 - 改完必须重启 MySQL 服务:
sudo systemctl restart mysql(Linux)或net stop mysql && net start mysql(Windows)
修复已有数据库和表的字符集(含数据迁移风险)
对已存在数据的库/表,不能只改元数据,必须用 CONVERT TO 触发实际字节重编码,否则旧数据仍按原编码解析。
先改数据库:
ALTER DATABASE `db_name` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
再逐个改表(注意:该操作会锁表,生产环境需评估窗口期):
ALTER TABLE `tb_name` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
常见误区:
- 只用
ALTER TABLE ... DEFAULT CHARACTER SET—— 这只改新字段默认值,不转换已有数据 - 跳过
CONVERT TO直接改列定义 —— 中文可能被截断或变成??? - 未检查字段本身是否支持:如
VARCHAR(255)在utf8mb4下实际最多存 191 个汉字(因 4 字节/字符),超长需扩大长度
导入 SQL 文件时中文变 ??? 的真实原因与解法
用 mysql -u root -p db 导入后中文全成问号,问题往往不在数据库,而在文件本身或客户端协商环节。
分三步排查:
- 用
file -i data.sql确认真实编码,不是编辑器显示的“UTF-8”;若有 BOM,用sed -i '1s/^\xef\xbb\xbf//' data.sql清除 - 检查
~/.my.cnf是否有[client]段且设置了default-character-set;若无,命令行需显式指定:mysql --default-character-set=utf8mb4 -u root -p db - 避免用 shell 重定向导入:它绕过 MySQL 客户端的字符集协商机制。优先改用
source /path/to/data.sql在 MySQL 会话内执行
真正麻烦的是混合编码文件——比如部分字段是 GBK 写入、部分是 UTF-8。这种必须先用 iconv 统一转码,不能硬导。











